forked from mia/Aegisub
Get audio styling ranges from the timing controller. Based on a patch by jfs.
Originally committed to SVN as r5878.
This commit is contained in:
parent
262d5195c5
commit
8d28b44773
13 changed files with 279 additions and 198 deletions
|
@ -336,17 +336,15 @@ void AudioController::SetTimingController(AudioTimingController *new_controller)
|
|||
{
|
||||
if (timing_controller.get() != new_controller) {
|
||||
timing_controller.reset(new_controller);
|
||||
timing_controller->AddMarkerMovedListener(std::tr1::bind(std::tr1::ref(AnnounceMarkerMoved)));
|
||||
timing_controller->AddLabelChangedListener(std::tr1::bind(std::tr1::ref(AnnounceLabelChanged)));
|
||||
timing_controller->AddMarkerMovedListener(bind(std::tr1::ref(AnnounceMarkerMoved)));
|
||||
timing_controller->AddLabelChangedListener(bind(std::tr1::ref(AnnounceLabelChanged)));
|
||||
timing_controller->AddUpdatedPrimaryRangeListener(&AudioController::OnTimingControllerUpdatedPrimaryRange, this);
|
||||
timing_controller->AddUpdatedStyleRangesListener(&AudioController::OnTimingControllerUpdatedStyleRanges, this);
|
||||
timing_controller->AddUpdatedStyleRangesListener(bind(std::tr1::ref(AnnounceStyleRangesChanged)));
|
||||
}
|
||||
|
||||
AnnounceTimingControllerChanged();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AudioController::OnTimingControllerUpdatedPrimaryRange()
|
||||
{
|
||||
if (playback_mode == PM_PrimaryRange)
|
||||
|
@ -357,12 +355,6 @@ void AudioController::OnTimingControllerUpdatedPrimaryRange()
|
|||
AnnounceSelectionChanged();
|
||||
}
|
||||
|
||||
|
||||
void AudioController::OnTimingControllerUpdatedStyleRanges()
|
||||
{
|
||||
/// @todo redraw and stuff, probably
|
||||
}
|
||||
|
||||
void AudioController::OnSubtitlesSave()
|
||||
{
|
||||
if (IsAudioOpen())
|
||||
|
|
|
@ -201,6 +201,9 @@ class AudioController : public wxEvtHandler, public AudioMarkerProvider, public
|
|||
/// The selected time range changed
|
||||
agi::signal::Signal<> AnnounceSelectionChanged;
|
||||
|
||||
/// The styling ranges have been updated by the timing controller
|
||||
agi::signal::Signal<> AnnounceStyleRangesChanged;
|
||||
|
||||
/// The audio output object
|
||||
AudioPlayer *player;
|
||||
|
||||
|
@ -390,6 +393,7 @@ public:
|
|||
DEFINE_SIGNAL_ADDERS(AnnouncePlaybackStop, AddPlaybackStopListener)
|
||||
DEFINE_SIGNAL_ADDERS(AnnounceTimingControllerChanged, AddTimingControllerListener)
|
||||
DEFINE_SIGNAL_ADDERS(AnnounceSelectionChanged, AddSelectionChangedListener)
|
||||
DEFINE_SIGNAL_ADDERS(AnnounceStyleRangesChanged, AddStyleRangesChangedListener)
|
||||
};
|
||||
|
||||
/// @class AudioMarker
|
||||
|
|
|
@ -494,8 +494,54 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class AudioStyleRangeMerger : public AudioRenderingStyleRanges {
|
||||
typedef std::map<int64_t, AudioRenderingStyle> style_map;
|
||||
public:
|
||||
typedef style_map::iterator iterator;
|
||||
|
||||
private:
|
||||
style_map points;
|
||||
|
||||
void Split(int64_t point)
|
||||
{
|
||||
iterator it = points.lower_bound(point);
|
||||
if (it == points.end() || it->first != point)
|
||||
{
|
||||
assert(it != points.begin());
|
||||
points[point] = (--it)->second;
|
||||
}
|
||||
}
|
||||
|
||||
void Restyle(int64_t start, int64_t end, AudioRenderingStyle style)
|
||||
{
|
||||
assert(points.lower_bound(end) != points.end());
|
||||
for (iterator pt = points.lower_bound(start); pt->first < end; ++pt)
|
||||
{
|
||||
if (style > pt->second)
|
||||
pt->second = style;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
AudioStyleRangeMerger()
|
||||
{
|
||||
points[0] = AudioStyle_Normal;
|
||||
}
|
||||
|
||||
void AddRange(int64_t start, int64_t end, AudioRenderingStyle style)
|
||||
{
|
||||
|
||||
if (start < 0) start = 0;
|
||||
if (end < start) return;
|
||||
|
||||
Split(start);
|
||||
Split(end);
|
||||
Restyle(start, end, style);
|
||||
}
|
||||
|
||||
iterator begin() { return points.begin(); }
|
||||
iterator end() { return points.end(); }
|
||||
};
|
||||
|
||||
AudioDisplay::AudioDisplay(wxWindow *parent, AudioController *controller, agi::Context *context)
|
||||
: wxWindow(parent, -1, wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS|wxBORDER_SIMPLE)
|
||||
|
@ -506,8 +552,9 @@ AudioDisplay::AudioDisplay(wxWindow *parent, AudioController *controller, agi::C
|
|||
, scrollbar(new AudioDisplayScrollbar(this))
|
||||
, timeline(new AudioDisplayTimeline(this))
|
||||
, dragged_object(0)
|
||||
, old_selection(0, 0)
|
||||
{
|
||||
style_ranges[0] = AudioStyle_Normal;
|
||||
|
||||
scroll_left = 0;
|
||||
pixel_audio_width = 0;
|
||||
scale_amplitude = 1.0;
|
||||
|
@ -521,6 +568,7 @@ AudioDisplay::AudioDisplay(wxWindow *parent, AudioController *controller, agi::C
|
|||
slots.push_back(controller->AddTimingControllerListener(&AudioDisplay::Refresh, this, true, (const wxRect*)0));
|
||||
slots.push_back(controller->AddMarkerMovedListener(&AudioDisplay::OnMarkerMoved, this));
|
||||
slots.push_back(controller->AddSelectionChangedListener(&AudioDisplay::OnSelectionChanged, this));
|
||||
slots.push_back(controller->AddStyleRangesChangedListener(&AudioDisplay::OnStyleRangesChanged, this));
|
||||
|
||||
OPT_SUB("Audio/Spectrum", &AudioDisplay::ReloadRenderingSettings, this);
|
||||
|
||||
|
@ -764,15 +812,9 @@ BEGIN_EVENT_TABLE(AudioDisplay, wxWindow)
|
|||
EVT_SET_FOCUS(AudioDisplay::OnFocus)
|
||||
EVT_KILL_FOCUS(AudioDisplay::OnFocus)
|
||||
EVT_KEY_DOWN(AudioDisplay::OnKeyDown)
|
||||
END_EVENT_TABLE()
|
||||
END_EVENT_TABLE();
|
||||
|
||||
|
||||
struct RedrawSubregion {
|
||||
int x1, x2;
|
||||
bool selected;
|
||||
RedrawSubregion(int x1, int x2, bool selected) : x1(x1), x2(x2), selected(selected) { }
|
||||
};
|
||||
|
||||
void AudioDisplay::OnPaint(wxPaintEvent& event)
|
||||
{
|
||||
wxAutoBufferedPaintDC dc(this);
|
||||
|
@ -793,11 +835,6 @@ void AudioDisplay::OnPaint(wxPaintEvent& event)
|
|||
bool redraw_scrollbar = false;
|
||||
bool redraw_timeline = false;
|
||||
|
||||
/// @todo Get rendering style ranges from timing controller instead
|
||||
SampleRange sel_samples(controller->GetPrimaryPlaybackRange());
|
||||
int selection_start = AbsoluteXFromSamples(sel_samples.begin());
|
||||
int selection_end = AbsoluteXFromSamples(sel_samples.end());
|
||||
|
||||
wxPoint client_org = GetClientAreaOrigin();
|
||||
for (wxRegionIterator region(GetUpdateRegion()); region; ++region)
|
||||
{
|
||||
|
@ -816,38 +853,31 @@ void AudioDisplay::OnPaint(wxPaintEvent& event)
|
|||
continue;
|
||||
}
|
||||
|
||||
// p1 -> p2 = before selection
|
||||
// p2 -> p3 = in selection
|
||||
// p3 -> p4 = after selection
|
||||
int p1 = scroll_left + updrect.x;
|
||||
int p2 = selection_start;
|
||||
int p3 = selection_end;
|
||||
int p4 = p1 + updrect.width;
|
||||
|
||||
std::vector<RedrawSubregion> subregions;
|
||||
|
||||
if (p1 < p2)
|
||||
subregions.push_back(RedrawSubregion(p1, std::min(p2, p4), false));
|
||||
if (p4 > p2 && p1 < p3)
|
||||
subregions.push_back(RedrawSubregion(std::max(p1, p2), std::min(p3, p4), true));
|
||||
if (p4 > p3)
|
||||
subregions.push_back(RedrawSubregion(std::max(p1, p3), p4, false));
|
||||
|
||||
int x = updrect.x;
|
||||
for (std::vector<RedrawSubregion>::iterator sr = subregions.begin(); sr != subregions.end(); ++sr)
|
||||
{
|
||||
audio_renderer->Render(dc, wxPoint(x, audio_top), sr->x1, sr->x2 - sr->x1, sr->selected);
|
||||
x += sr->x2 - sr->x1;
|
||||
}
|
||||
|
||||
const int foot_size = 6;
|
||||
SampleRange updrectsamples(
|
||||
SampleRange updsamples(
|
||||
SamplesFromRelativeX(updrect.x - foot_size),
|
||||
SamplesFromRelativeX(updrect.x + updrect.width + foot_size));
|
||||
|
||||
std::map<int64_t, int>::iterator pt = style_ranges.upper_bound(updsamples.begin());
|
||||
std::map<int64_t, int>::iterator pe = style_ranges.upper_bound(updsamples.end());
|
||||
|
||||
if (pt != style_ranges.begin())
|
||||
--pt;
|
||||
|
||||
while (pt != pe)
|
||||
{
|
||||
AudioRenderingStyle range_style = static_cast<AudioRenderingStyle>(pt->second);
|
||||
int range_x1 = std::max(updrect.x, RelativeXFromSamples(pt->first));
|
||||
int range_x2 = (++pt == pe) ? updrect.x + updrect.width : RelativeXFromSamples(pt->first);
|
||||
|
||||
if (range_x2 > range_x1)
|
||||
{
|
||||
audio_renderer->Render(dc, wxPoint(range_x1, audio_top), range_x1, range_x2 - range_x1, range_style);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw markers on top of it all
|
||||
AudioMarkerVector markers;
|
||||
controller->GetMarkers(updrectsamples, markers);
|
||||
controller->GetMarkers(updsamples, markers);
|
||||
wxDCPenChanger pen_retainer(dc, wxPen());
|
||||
wxDCBrushChanger brush_retainer(dc, wxBrush());
|
||||
for (AudioMarkerVector::iterator marker_i = markers.begin(); marker_i != markers.end(); ++marker_i)
|
||||
|
@ -876,7 +906,7 @@ void AudioDisplay::OnPaint(wxPaintEvent& event)
|
|||
|
||||
// Draw labels
|
||||
std::vector<AudioLabelProvider::AudioLabel> labels;
|
||||
controller->GetLabels(updrectsamples, labels);
|
||||
controller->GetLabels(updsamples, labels);
|
||||
if (!labels.empty())
|
||||
{
|
||||
wxDCFontChanger fc(dc);
|
||||
|
@ -943,7 +973,7 @@ void AudioDisplay::OnPaint(wxPaintEvent& event)
|
|||
track_cursor_label_rect.SetPosition(label_pos);
|
||||
track_cursor_label_rect.SetSize(label_size);
|
||||
if (need_extra_redraw)
|
||||
RefreshRect(track_cursor_label_rect);
|
||||
RefreshRect(track_cursor_label_rect, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -976,11 +1006,11 @@ void AudioDisplay::SetTrackCursor(int new_pos, bool show_time)
|
|||
int old_pos = track_cursor_pos;
|
||||
track_cursor_pos = new_pos;
|
||||
|
||||
RefreshRect(wxRect(old_pos - scroll_left - 0, audio_top, 1, audio_height));
|
||||
RefreshRect(wxRect(new_pos - scroll_left - 0, audio_top, 1, audio_height));
|
||||
RefreshRect(wxRect(old_pos - scroll_left - 0, audio_top, 1, audio_height), false);
|
||||
RefreshRect(wxRect(new_pos - scroll_left - 0, audio_top, 1, audio_height), false);
|
||||
|
||||
// Make sure the old label gets cleared away
|
||||
RefreshRect(track_cursor_label_rect);
|
||||
RefreshRect(track_cursor_label_rect, false);
|
||||
|
||||
if (show_time)
|
||||
{
|
||||
|
@ -988,7 +1018,7 @@ void AudioDisplay::SetTrackCursor(int new_pos, bool show_time)
|
|||
new_label_time.SetMS(controller->MillisecondsFromSamples(SamplesFromAbsoluteX(track_cursor_pos)));
|
||||
track_cursor_label = new_label_time.GetASSFormated();
|
||||
track_cursor_label_rect.x += new_pos - old_pos;
|
||||
RefreshRect(track_cursor_label_rect);
|
||||
RefreshRect(track_cursor_label_rect, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1148,7 +1178,7 @@ void AudioDisplay::OnSize(wxSizeEvent &event)
|
|||
void AudioDisplay::OnFocus(wxFocusEvent &event)
|
||||
{
|
||||
// The scrollbar indicates focus so repaint that
|
||||
RefreshRect(scrollbar->GetBounds());
|
||||
RefreshRect(scrollbar->GetBounds(), false);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1174,42 +1204,76 @@ void AudioDisplay::OnPlaybackPosition(int64_t sample_position)
|
|||
|
||||
void AudioDisplay::OnSelectionChanged()
|
||||
{
|
||||
/// @todo Handle rendering style ranges from timing controller instead
|
||||
SampleRange sel(controller->GetPrimaryPlaybackRange());
|
||||
scrollbar->SetSelection(AbsoluteXFromSamples(sel.begin()), AbsoluteXFromSamples(sel.length()));
|
||||
|
||||
if (OPT_GET("Audio/Auto/Scroll")->GetBool())
|
||||
{
|
||||
ScrollSampleRangeInView(sel);
|
||||
|
||||
int s1 = RelativeXFromSamples(sel.begin());
|
||||
int e1 = RelativeXFromSamples(sel.end());
|
||||
int s2 = RelativeXFromSamples(old_selection.begin());
|
||||
int e2 = RelativeXFromSamples(old_selection.end());
|
||||
|
||||
if (sel.overlaps(old_selection))
|
||||
{
|
||||
// Only redraw the parts of the selection that changed, to avoid flicker
|
||||
if (s1 != s2)
|
||||
{
|
||||
RefreshRect(wxRect(std::min(s1, s2)-10, audio_top, abs(s1-s2)+20, audio_height));
|
||||
}
|
||||
if (e1 != e2)
|
||||
{
|
||||
RefreshRect(wxRect(std::min(e1, e2)-10, audio_top, abs(e1-e2)+20, audio_height));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RefreshRect(wxRect(s1 - 10, audio_top, e1 + 20, audio_height));
|
||||
RefreshRect(wxRect(s2 - 10, audio_top, e2 + 20, audio_height));
|
||||
}
|
||||
|
||||
RefreshRect(scrollbar->GetBounds());
|
||||
RefreshRect(scrollbar->GetBounds(), false);
|
||||
}
|
||||
|
||||
old_selection = sel;
|
||||
void AudioDisplay::OnStyleRangesChanged()
|
||||
{
|
||||
AudioStyleRangeMerger asrm;
|
||||
controller->GetTimingController()->GetRenderingStyles(asrm);
|
||||
|
||||
std::map<int64_t, int> old_style_ranges;
|
||||
swap(old_style_ranges, style_ranges);
|
||||
style_ranges.insert(asrm.begin(), asrm.end());
|
||||
|
||||
std::map<int64_t, int>::iterator old_style_it = old_style_ranges.begin();
|
||||
std::map<int64_t, int>::iterator new_style_it = style_ranges.begin();
|
||||
|
||||
int old_style = old_style_it->second;
|
||||
int new_style = new_style_it->second;
|
||||
int64_t range_start = 0;
|
||||
|
||||
// Repaint each range which has changed
|
||||
while (old_style_it != old_style_ranges.end() || new_style_it != style_ranges.end())
|
||||
{
|
||||
if (new_style_it == style_ranges.end() || (old_style_it != old_style_ranges.end() && old_style_it->first <= new_style_it->first))
|
||||
{
|
||||
if (old_style != new_style)
|
||||
Redraw(range_start, old_style_it->first);
|
||||
old_style = old_style_it->second;
|
||||
range_start = old_style_it->first;
|
||||
++old_style_it;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (old_style != new_style)
|
||||
Redraw(range_start, new_style_it->first);
|
||||
new_style = new_style_it->second;
|
||||
range_start = new_style_it->first;
|
||||
++new_style_it;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill in the last style range
|
||||
if (old_style != new_style)
|
||||
{
|
||||
Redraw(range_start, SamplesFromRelativeX(GetClientSize().GetWidth()));
|
||||
}
|
||||
}
|
||||
|
||||
void AudioDisplay::Redraw(int64_t sample_start, int64_t sample_end)
|
||||
{
|
||||
if (sample_start == sample_end) return;
|
||||
|
||||
sample_start = RelativeXFromSamples(sample_start) - foot_size;
|
||||
sample_end = RelativeXFromSamples(sample_end) + foot_size;
|
||||
|
||||
if (sample_end >= 0 && sample_start <= GetClientSize().GetWidth())
|
||||
{
|
||||
RefreshRect(wxRect(sample_start, audio_top, sample_end, audio_height), false);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioDisplay::OnMarkerMoved()
|
||||
{
|
||||
/// @todo investigate if it's worth refreshing only the changed spots
|
||||
RefreshRect(wxRect(0, audio_top, GetClientSize().GetWidth(), audio_height));
|
||||
RefreshRect(wxRect(0, audio_top, GetClientSize().GetWidth(), audio_height), false);
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ public:
|
|||
/// 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:
|
||||
|
||||
std::list<agi::signal::Connection> slots;
|
||||
agi::Context *context;
|
||||
|
||||
|
@ -146,6 +146,8 @@ private:
|
|||
/// Height of main audio area in pixels
|
||||
int audio_height;
|
||||
|
||||
/// Width of the audio marker feet in pixels
|
||||
static const int foot_size = 6;
|
||||
|
||||
/// Zoom level given as a number, see SetZoomLevel for details
|
||||
int zoom_level;
|
||||
|
@ -163,8 +165,8 @@ private:
|
|||
/// @brief Remove the tracking cursor from the display
|
||||
void RemoveTrackCursor();
|
||||
|
||||
/// Previous audio selection for optimizing redraw when selection changes
|
||||
SampleRange old_selection;
|
||||
/// Previous style ranges for optimizing redraw when ranges change
|
||||
std::map<int64_t, int> style_ranges;
|
||||
|
||||
/// @brief Reload all rendering settings from Options and reset caches
|
||||
///
|
||||
|
@ -172,6 +174,11 @@ private:
|
|||
/// in Options and need to be reloaded to take effect.
|
||||
void ReloadRenderingSettings();
|
||||
|
||||
/// @brief Repaint a range of samples
|
||||
/// @param sample_start First sample to repaint
|
||||
/// @param sample_end Last sample to repaint
|
||||
void Redraw(int64_t sample_start, int64_t sample_end);
|
||||
|
||||
/// wxWidgets paint event
|
||||
void OnPaint(wxPaintEvent &event);
|
||||
/// wxWidgets mouse input event
|
||||
|
@ -187,10 +194,10 @@ private:
|
|||
void OnAudioOpen(AudioProvider *provider);
|
||||
void OnPlaybackPosition(int64_t sample_position);
|
||||
void OnSelectionChanged();
|
||||
void OnStyleRangesChanged();
|
||||
void OnMarkerMoved();
|
||||
|
||||
public:
|
||||
|
||||
AudioDisplay(wxWindow *parent, AudioController *controller, agi::Context *context);
|
||||
~AudioDisplay();
|
||||
|
||||
|
|
|
@ -46,9 +46,12 @@
|
|||
#include "audio_renderer.h"
|
||||
#include "include/aegisub/audio_provider.h"
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
template<class C, class F> static void for_each(C &container, F const& func)
|
||||
{
|
||||
std::for_each(container.begin(), container.end(), func);
|
||||
}
|
||||
|
||||
using std::tr1::placeholders::_1;
|
||||
|
||||
AudioRendererBitmapCacheBitmapFactory::AudioRendererBitmapCacheBitmapFactory(AudioRenderer *_renderer)
|
||||
{
|
||||
|
@ -80,19 +83,18 @@ size_t AudioRendererBitmapCacheBitmapFactory::GetBlockSize() const
|
|||
|
||||
AudioRenderer::AudioRenderer()
|
||||
: cache_bitmap_width(32) // arbitrary value for now
|
||||
, bitmaps_normal(256, AudioRendererBitmapCacheBitmapFactory(this))
|
||||
, bitmaps_selected(256, AudioRendererBitmapCacheBitmapFactory(this))
|
||||
, cache_bitmap_maxsize(0)
|
||||
, cache_renderer_maxsize(0)
|
||||
, renderer(0)
|
||||
, provider(0)
|
||||
{
|
||||
bitmaps.resize(AudioStyle_MAX, AudioRendererBitmapCache(256, AudioRendererBitmapCacheBitmapFactory(this)));
|
||||
|
||||
// Make sure there's *some* values for those fields, and in the caches
|
||||
SetSamplesPerPixel(1);
|
||||
SetHeight(1);
|
||||
}
|
||||
|
||||
|
||||
AudioRenderer::~AudioRenderer()
|
||||
{
|
||||
// Nothing to do, everything is auto-allocated
|
||||
|
@ -183,26 +185,22 @@ void AudioRenderer::ResetBlockCount()
|
|||
{
|
||||
size_t rendered_width = (size_t)((provider->GetNumSamples() + pixel_samples - 1) / pixel_samples);
|
||||
cache_numblocks = rendered_width / cache_bitmap_width;
|
||||
bitmaps_normal.SetBlockCount(cache_numblocks);
|
||||
bitmaps_selected.SetBlockCount(cache_numblocks);
|
||||
for_each(bitmaps, bind(&AudioRendererBitmapCache::SetBlockCount, _1, cache_numblocks));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
wxBitmap AudioRenderer::GetCachedBitmap(int i, bool selected)
|
||||
wxBitmap AudioRenderer::GetCachedBitmap(int i, AudioRenderingStyle style)
|
||||
{
|
||||
assert(provider);
|
||||
assert(renderer);
|
||||
|
||||
// Pick the cache to use
|
||||
AudioRendererBitmapCache *cache = selected ? &bitmaps_selected : &bitmaps_normal;
|
||||
|
||||
bool created = false;
|
||||
wxBitmap *bmp = cache->Get(i, &created);
|
||||
wxBitmap *bmp = bitmaps[style].Get(i, &created);
|
||||
assert(bmp);
|
||||
if (created)
|
||||
{
|
||||
renderer->Render(*bmp, i*cache_bitmap_width, selected);
|
||||
renderer->Render(*bmp, i*cache_bitmap_width, style);
|
||||
}
|
||||
|
||||
assert(bmp->IsOk());
|
||||
|
@ -210,7 +208,7 @@ wxBitmap AudioRenderer::GetCachedBitmap(int i, bool selected)
|
|||
}
|
||||
|
||||
|
||||
void AudioRenderer::Render(wxDC &dc, wxPoint origin, int start, int length, bool selected)
|
||||
void AudioRenderer::Render(wxDC &dc, wxPoint origin, int start, int length, AudioRenderingStyle style)
|
||||
{
|
||||
assert(start >= 0);
|
||||
|
||||
|
@ -257,7 +255,7 @@ void AudioRenderer::Render(wxDC &dc, wxPoint origin, int start, int length, bool
|
|||
else if (firstbitmap == lastbitmap)
|
||||
{
|
||||
const int renderwidth = lastbitmapoffset - firstbitmapoffset;
|
||||
wxBitmap bmp = GetCachedBitmap(firstbitmap, selected);
|
||||
wxBitmap bmp = GetCachedBitmap(firstbitmap, style);
|
||||
wxMemoryDC bmpdc(bmp);
|
||||
dc.Blit(origin, wxSize(renderwidth, pixel_height), &bmpdc, wxPoint(firstbitmapoffset, 0));
|
||||
origin.x += renderwidth;
|
||||
|
@ -267,7 +265,7 @@ void AudioRenderer::Render(wxDC &dc, wxPoint origin, int start, int length, bool
|
|||
wxBitmap bmp;
|
||||
|
||||
{
|
||||
bmp = GetCachedBitmap(firstbitmap, selected);
|
||||
bmp = GetCachedBitmap(firstbitmap, style);
|
||||
// Can't use dc.DrawBitmap here because we need to clip the bitmap
|
||||
wxMemoryDC bmpdc(bmp);
|
||||
dc.Blit(origin, wxSize(cache_bitmap_width-firstbitmapoffset, pixel_height),
|
||||
|
@ -277,13 +275,13 @@ void AudioRenderer::Render(wxDC &dc, wxPoint origin, int start, int length, bool
|
|||
|
||||
for (int i = firstbitmap+1; i < lastbitmap; ++i)
|
||||
{
|
||||
bmp = GetCachedBitmap(i, selected);
|
||||
bmp = GetCachedBitmap(i, style);
|
||||
dc.DrawBitmap(bmp, origin);
|
||||
origin.x += cache_bitmap_width;
|
||||
}
|
||||
|
||||
{
|
||||
bmp = GetCachedBitmap(lastbitmap, selected);
|
||||
bmp = GetCachedBitmap(lastbitmap, style);
|
||||
// We also need clipping here
|
||||
wxMemoryDC bmpdc(bmp);
|
||||
dc.Blit(origin, wxSize(lastbitmapoffset+1, pixel_height), &bmpdc, wxPoint(0, 0));
|
||||
|
@ -294,26 +292,20 @@ void AudioRenderer::Render(wxDC &dc, wxPoint origin, int start, int length, bool
|
|||
// Now render blank audio from origin to end
|
||||
if (origin.x < lastx)
|
||||
{
|
||||
renderer->RenderBlank(dc, wxRect(origin.x-1, origin.y, lastx-origin.x+1, pixel_height), selected);
|
||||
renderer->RenderBlank(dc, wxRect(origin.x-1, origin.y, lastx-origin.x+1, pixel_height), style);
|
||||
}
|
||||
|
||||
if (selected)
|
||||
bitmaps_selected.Age(cache_bitmap_maxsize);
|
||||
else
|
||||
bitmaps_normal.Age(cache_bitmap_maxsize);
|
||||
bitmaps[style].Age(cache_bitmap_maxsize);
|
||||
renderer->AgeCache(cache_renderer_maxsize);
|
||||
}
|
||||
|
||||
|
||||
void AudioRenderer::Invalidate()
|
||||
{
|
||||
bitmaps_normal.Age(0);
|
||||
bitmaps_selected.Age(0);
|
||||
for_each(bitmaps, bind(&AudioRendererBitmapCache::Age, _1, 0));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AudioRendererBitmapProvider::SetProvider(AudioProvider *_provider)
|
||||
{
|
||||
if (provider == _provider) return;
|
||||
|
@ -342,4 +334,3 @@ void AudioRendererBitmapProvider::SetAmplitudeScale(float _amplitude_scale)
|
|||
|
||||
OnSetAmplitudeScale();
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
|
||||
#ifndef AGI_PRE
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <wx/dc.h>
|
||||
#include <wx/gdicmn.h>
|
||||
|
@ -52,6 +53,41 @@ class AudioProvider;
|
|||
class AudioRendererBitmapProvider;
|
||||
class AudioRenderer;
|
||||
|
||||
/// @brief Styles audio may be rendered in
|
||||
///
|
||||
/// The constants are ordered by priority:
|
||||
/// Selected has highest priority and should overlap active, which should
|
||||
/// overlap inactive, which should overlap normal regions.
|
||||
enum AudioRenderingStyle {
|
||||
/// Regular audio with no special properties
|
||||
AudioStyle_Normal,
|
||||
/// Audio belonging to objects that can not be manipulated currently
|
||||
AudioStyle_Inactive,
|
||||
/// Audio that may be manipulated indirectly, usually part of selected lines
|
||||
AudioStyle_Active,
|
||||
/// Primary selection for work, usually coinciding with the primary playback range
|
||||
AudioStyle_Selected,
|
||||
/// Number of audio styles
|
||||
AudioStyle_MAX
|
||||
};
|
||||
|
||||
|
||||
/// @class AudioRenderingStyleRanges
|
||||
/// @brief Abstract container for ranges of audio rendering styles
|
||||
///
|
||||
/// Interface for producers of audio rendering ranges, consumers should implement
|
||||
/// this interface for objects to pass to producers.
|
||||
class AudioRenderingStyleRanges {
|
||||
public:
|
||||
/// @brief Add a range to the line
|
||||
/// @param start First sample index in range
|
||||
/// @param end One past last sample index in range
|
||||
/// @param style Style of the range added
|
||||
virtual void AddRange(int64_t start, int64_t end, AudioRenderingStyle style) = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// @class AudioRendererBitmapCacheBitmapFactory
|
||||
/// @brief Produces wxBitmap objects for DataBlockCache storage for the audio renderer
|
||||
struct AudioRendererBitmapCacheBitmapFactory {
|
||||
|
@ -104,10 +140,8 @@ class AudioRenderer {
|
|||
/// Width of bitmaps to store in cache
|
||||
const int cache_bitmap_width;
|
||||
|
||||
/// Cached bitmaps for normal audio ranges
|
||||
AudioRendererBitmapCache bitmaps_normal;
|
||||
/// Cached bitmaps for marked (selected) audio ranges
|
||||
AudioRendererBitmapCache bitmaps_selected;
|
||||
/// Cached bitmaps for audio ranges
|
||||
std::vector<AudioRendererBitmapCache> bitmaps;
|
||||
/// Number of blocks in the bitmap caches
|
||||
size_t cache_numblocks;
|
||||
/// The maximum allowed size of each bitmap cache, in bytes
|
||||
|
@ -122,13 +156,13 @@ class AudioRenderer {
|
|||
AudioProvider *provider;
|
||||
|
||||
/// @brief Make sure bitmap index i is in cache
|
||||
/// @param i Index of bitmap to get into cache
|
||||
/// @param selected Whether to get a "selected" state bitmap or not
|
||||
/// @param i Index of bitmap to get into cache
|
||||
/// @param style Rendering style required for bitmap
|
||||
/// @return The requested bitmap
|
||||
///
|
||||
/// Will attempt retrieving the requested bitmap from the cache, creating it
|
||||
/// if the cache doesn't have it.
|
||||
wxBitmap GetCachedBitmap(int i, bool selected);
|
||||
wxBitmap GetCachedBitmap(int i, AudioRenderingStyle style);
|
||||
|
||||
/// @brief Update the block count in the bitmap caches
|
||||
///
|
||||
|
@ -230,11 +264,11 @@ public:
|
|||
/// @param origin Top left corner to render at, in the DC's coordinates
|
||||
/// @param start First pixel from beginning of the audio stream to render
|
||||
/// @param length Number of pixels of audio to render
|
||||
/// @param selected Whether to render the audio as being selected or not
|
||||
/// @param style Style to render audio in
|
||||
///
|
||||
/// The first audio sample rendered is start*pixel_samples, and the number
|
||||
/// of audio samples rendered is length*pixel_samples.
|
||||
void Render(wxDC &dc, wxPoint origin, int start, int length, bool selected);
|
||||
void Render(wxDC &dc, wxPoint origin, int start, int length, AudioRenderingStyle style);
|
||||
|
||||
/// @brief Invalidate all cached data
|
||||
///
|
||||
|
@ -284,22 +318,22 @@ public:
|
|||
virtual ~AudioRendererBitmapProvider() { }
|
||||
|
||||
/// @brief Rendering function
|
||||
/// @param bmp Bitmap to render to
|
||||
/// @param start First pixel from beginning of the audio stream to render
|
||||
/// @param selected Whether to render the audio as being selected or not
|
||||
/// @param bmp Bitmap to render to
|
||||
/// @param start First pixel from beginning of the audio stream to render
|
||||
/// @param style Style to render audio in
|
||||
///
|
||||
/// Deriving classes must implement this method. The bitmap in bmp holds
|
||||
/// the width and height to render.
|
||||
virtual void Render(wxBitmap &bmp, int start, bool selected) = 0;
|
||||
virtual void Render(wxBitmap &bmp, int start, AudioRenderingStyle style) = 0;
|
||||
|
||||
/// @brief Blank audio rendering function
|
||||
/// @param dc The device context to render to
|
||||
/// @param rect The rectangle to fill with the image of blank audio
|
||||
/// @param selected Whether to render as being selected or not
|
||||
/// @param dc The device context to render to
|
||||
/// @param rect The rectangle to fill with the image of blank audio
|
||||
/// @param style Style to render audio in
|
||||
///
|
||||
/// Deriving classes must implement this method. The rectangle has the height
|
||||
/// of the entire canvas the audio is being rendered in.
|
||||
virtual void RenderBlank(wxDC &dc, const wxRect &rect, bool selected) = 0;
|
||||
virtual void RenderBlank(wxDC &dc, const wxRect &rect, AudioRenderingStyle style) = 0;
|
||||
|
||||
/// @brief Change audio provider
|
||||
/// @param provider Audio provider to change to
|
||||
|
|
|
@ -264,7 +264,7 @@ void AudioSpectrumRenderer::FillBlock(size_t block_index, float *block)
|
|||
}
|
||||
|
||||
|
||||
void AudioSpectrumRenderer::Render(wxBitmap &bmp, int start, bool selected)
|
||||
void AudioSpectrumRenderer::Render(wxBitmap &bmp, int start, AudioRenderingStyle style)
|
||||
{
|
||||
if (!cache)
|
||||
return;
|
||||
|
@ -284,7 +284,7 @@ void AudioSpectrumRenderer::Render(wxBitmap &bmp, int start, bool selected)
|
|||
ptrdiff_t stride = img.GetWidth()*3;
|
||||
int imgheight = img.GetHeight();
|
||||
|
||||
AudioColorScheme *pal = selected ? &colors_selected : &colors_normal;
|
||||
AudioColorScheme *pal = style == AudioStyle_Selected ? &colors_selected : &colors_normal;
|
||||
|
||||
/// @todo Make minband and maxband configurable
|
||||
int minband = 0;
|
||||
|
@ -341,10 +341,10 @@ void AudioSpectrumRenderer::Render(wxBitmap &bmp, int start, bool selected)
|
|||
}
|
||||
|
||||
|
||||
void AudioSpectrumRenderer::RenderBlank(wxDC &dc, const wxRect &rect, bool selected)
|
||||
void AudioSpectrumRenderer::RenderBlank(wxDC &dc, const wxRect &rect, AudioRenderingStyle style)
|
||||
{
|
||||
// Get the colour of silence
|
||||
AudioColorScheme *pal = selected ? &colors_selected : &colors_normal;
|
||||
AudioColorScheme *pal = style == AudioStyle_Selected ? &colors_selected : &colors_normal;
|
||||
unsigned char color_raw[4];
|
||||
pal->map(0.0, color_raw);
|
||||
wxColour col(color_raw[0], color_raw[1], color_raw[2]);
|
||||
|
|
|
@ -115,13 +115,13 @@ public:
|
|||
virtual ~AudioSpectrumRenderer();
|
||||
|
||||
/// @brief Render a range of audio spectrum
|
||||
/// @param bmp [in,out] Bitmap to render into, also carries lenght information
|
||||
/// @param start First column of pixel data in display to render
|
||||
/// @param selected Whether to use the alternate colour scheme
|
||||
void Render(wxBitmap &bmp, int start, bool selected);
|
||||
/// @param bmp [in,out] Bitmap to render into, also carries lenght information
|
||||
/// @param start First column of pixel data in display to render
|
||||
/// @param style Style to render audio in
|
||||
void Render(wxBitmap &bmp, int start, AudioRenderingStyle style);
|
||||
|
||||
/// @brief Render blank area
|
||||
void RenderBlank(wxDC &dc, const wxRect &rect, bool selected);
|
||||
void RenderBlank(wxDC &dc, const wxRect &rect, AudioRenderingStyle style);
|
||||
|
||||
/// @brief Set the derivation resolution
|
||||
/// @param derivation_size Binary logarithm of number of samples to use in deriving frequency-power data
|
||||
|
|
|
@ -71,13 +71,13 @@ AudioWaveformRenderer::~AudioWaveformRenderer()
|
|||
}
|
||||
|
||||
|
||||
void AudioWaveformRenderer::Render(wxBitmap &bmp, int start, bool selected)
|
||||
void AudioWaveformRenderer::Render(wxBitmap &bmp, int start, AudioRenderingStyle style)
|
||||
{
|
||||
wxMemoryDC dc(bmp);
|
||||
wxRect rect(wxPoint(0, 0), bmp.GetSize());
|
||||
int midpoint = rect.height / 2;
|
||||
|
||||
AudioColorScheme *pal = selected ? &colors_selected : &colors_normal;
|
||||
AudioColorScheme *pal = style == AudioStyle_Selected ? &colors_selected : &colors_normal;
|
||||
|
||||
// Fill the background
|
||||
dc.SetBrush(wxBrush(pal->get(0.0f)));
|
||||
|
@ -140,9 +140,9 @@ void AudioWaveformRenderer::Render(wxBitmap &bmp, int start, bool selected)
|
|||
}
|
||||
|
||||
|
||||
void AudioWaveformRenderer::RenderBlank(wxDC &dc, const wxRect &rect, bool selected)
|
||||
void AudioWaveformRenderer::RenderBlank(wxDC &dc, const wxRect &rect, AudioRenderingStyle style)
|
||||
{
|
||||
AudioColorScheme *pal = selected ? &colors_selected : &colors_normal;
|
||||
AudioColorScheme *pal = style == AudioStyle_Selected ? &colors_selected : &colors_normal;
|
||||
|
||||
wxColor line(pal->get(1.0));
|
||||
wxColor bg(pal->get(0.0));
|
||||
|
|
|
@ -61,13 +61,13 @@ public:
|
|||
virtual ~AudioWaveformRenderer();
|
||||
|
||||
/// @brief Render a range of audio waveform
|
||||
/// @param bmp [in,out] Bitmap to render into, also carries lenght information
|
||||
/// @param start First column of pixel data in display to render
|
||||
/// @param selected Whether to use the alternate colour scheme
|
||||
void Render(wxBitmap &bmp, int start, bool selected);
|
||||
/// @param bmp [in,out] Bitmap to render into, also carries lenght information
|
||||
/// @param start First column of pixel data in display to render
|
||||
/// @param style Style to render audio in
|
||||
void Render(wxBitmap &bmp, int start, AudioRenderingStyle style);
|
||||
|
||||
/// @brief Render blank area
|
||||
void RenderBlank(wxDC &dc, const wxRect &rect, bool selected);
|
||||
void RenderBlank(wxDC &dc, const wxRect &rect, AudioRenderingStyle style);
|
||||
|
||||
/// @brief Cleans up the cache
|
||||
/// @param max_size Maximum size in bytes for the cache
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
class AssDialogue;
|
||||
class AssFile;
|
||||
class AssKaraoke;
|
||||
class AudioRenderingStyleRanges;
|
||||
namespace agi { struct Context; }
|
||||
|
||||
#include "audio_controller.h"
|
||||
|
@ -79,6 +80,10 @@ public:
|
|||
/// currently.
|
||||
virtual SampleRange GetPrimaryPlaybackRange() const = 0;
|
||||
|
||||
/// @brief Get all rendering style ranges
|
||||
/// @param[out] swpts Rendering ranges will be added to this
|
||||
virtual void GetRenderingStyles(AudioRenderingStyleRanges &ranges) 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.
|
||||
///
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "ass_time.h"
|
||||
#include "audio_controller.h"
|
||||
#include "audio_marker_provider_keyframes.h"
|
||||
#include "audio_renderer.h"
|
||||
#include "audio_timing.h"
|
||||
#include "include/aegisub/context.h"
|
||||
#include "main.h"
|
||||
|
@ -106,8 +107,10 @@ public:
|
|||
/// This checks that the markers aren't already part of a pair, and then
|
||||
/// sets their "other" field. Positions and styles aren't affected.
|
||||
static void InitPair(AudioMarkerDialogueTiming *marker1, AudioMarkerDialogueTiming *marker2);
|
||||
};
|
||||
|
||||
/// Implicit decay to the position of the marker
|
||||
operator int64_t() const { return position; }
|
||||
};
|
||||
|
||||
|
||||
/// @class AudioTimingControllerDialogue
|
||||
|
@ -176,6 +179,7 @@ public:
|
|||
wxString GetWarningMessage() const;
|
||||
SampleRange GetIdealVisibleSampleRange() const;
|
||||
SampleRange GetPrimaryPlaybackRange() const;
|
||||
void GetRenderingStyles(AudioRenderingStyleRanges &ranges) const;
|
||||
bool HasLabels() const { return false; }
|
||||
void GetLabels(SampleRange const& range, std::vector<AudioLabel> &out) const { }
|
||||
void Next();
|
||||
|
@ -195,8 +199,6 @@ public:
|
|||
~AudioTimingControllerDialogue();
|
||||
};
|
||||
|
||||
|
||||
|
||||
AudioTimingController *CreateDialogueTimingController(agi::Context *c)
|
||||
{
|
||||
return new AudioTimingControllerDialogue(c);
|
||||
|
@ -226,7 +228,6 @@ void AudioMarkerDialogueTiming::SetPosition(int64_t new_position)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
AudioMarkerDialogueTiming::AudioMarkerDialogueTiming()
|
||||
: other(0)
|
||||
, position(0)
|
||||
|
@ -238,7 +239,6 @@ AudioMarkerDialogueTiming::AudioMarkerDialogueTiming()
|
|||
// Nothing more to do
|
||||
}
|
||||
|
||||
|
||||
void AudioMarkerDialogueTiming::InitPair(AudioMarkerDialogueTiming *marker1, AudioMarkerDialogueTiming *marker2)
|
||||
{
|
||||
assert(marker1->other == 0);
|
||||
|
@ -248,8 +248,6 @@ void AudioMarkerDialogueTiming::InitPair(AudioMarkerDialogueTiming *marker1, Aud
|
|||
marker2->other = marker1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// AudioTimingControllerDialogue
|
||||
|
||||
AudioTimingControllerDialogue::AudioTimingControllerDialogue(agi::Context *c)
|
||||
|
@ -279,35 +277,31 @@ AudioTimingControllerDialogue::~AudioTimingControllerDialogue()
|
|||
context->selectionController->RemoveSelectionListener(this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
AudioMarkerDialogueTiming *AudioTimingControllerDialogue::GetLeftMarker()
|
||||
{
|
||||
return markers[0].GetPosition() < markers[1].GetPosition() ? &markers[0] : &markers[1];
|
||||
return markers[0] < markers[1] ? &markers[0] : &markers[1];
|
||||
}
|
||||
|
||||
const AudioMarkerDialogueTiming *AudioTimingControllerDialogue::GetLeftMarker() const
|
||||
{
|
||||
return markers[0].GetPosition() < markers[1].GetPosition() ? &markers[0] : &markers[1];
|
||||
return &std::min(markers[0], markers[1]);
|
||||
}
|
||||
|
||||
AudioMarkerDialogueTiming *AudioTimingControllerDialogue::GetRightMarker()
|
||||
{
|
||||
return markers[0].GetPosition() < markers[1].GetPosition() ? &markers[1] : &markers[0];
|
||||
return markers[0] < markers[1] ? &markers[1] : &markers[0];
|
||||
}
|
||||
|
||||
const AudioMarkerDialogueTiming *AudioTimingControllerDialogue::GetRightMarker() const
|
||||
{
|
||||
return markers[0].GetPosition() < markers[1].GetPosition() ? &markers[1] : &markers[0];
|
||||
return &std::max(markers[0], markers[1]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AudioTimingControllerDialogue::GetMarkers(const SampleRange &range, AudioMarkerVector &out_markers) const
|
||||
{
|
||||
if (range.contains(markers[0].GetPosition()))
|
||||
if (range.contains(markers[0]))
|
||||
out_markers.push_back(&markers[0]);
|
||||
if (range.contains(markers[1].GetPosition()))
|
||||
if (range.contains(markers[1]))
|
||||
out_markers.push_back(&markers[1]);
|
||||
|
||||
keyframes_provider.GetMarkers(range, out_markers);
|
||||
|
@ -331,49 +325,42 @@ void AudioTimingControllerDialogue::OnFileChanged(int type) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
wxString AudioTimingControllerDialogue::GetWarningMessage() const
|
||||
{
|
||||
// We have no warning messages currently, maybe add the old "Modified" message back later?
|
||||
return wxString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
SampleRange AudioTimingControllerDialogue::GetIdealVisibleSampleRange() const
|
||||
{
|
||||
return GetPrimaryPlaybackRange();
|
||||
}
|
||||
|
||||
|
||||
|
||||
SampleRange AudioTimingControllerDialogue::GetPrimaryPlaybackRange() const
|
||||
{
|
||||
return SampleRange(
|
||||
GetLeftMarker()->GetPosition(),
|
||||
GetRightMarker()->GetPosition());
|
||||
return SampleRange(*GetLeftMarker(), *GetRightMarker());
|
||||
}
|
||||
|
||||
|
||||
void AudioTimingControllerDialogue::GetRenderingStyles(AudioRenderingStyleRanges &ranges) const
|
||||
{
|
||||
ranges.AddRange(*GetLeftMarker(), *GetRightMarker(), AudioStyle_Selected);
|
||||
/// @todo Find inactive and non-selected lines to add to styles
|
||||
}
|
||||
|
||||
void AudioTimingControllerDialogue::Next()
|
||||
{
|
||||
context->selectionController->NextLine();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AudioTimingControllerDialogue::Prev()
|
||||
{
|
||||
context->selectionController->PrevLine();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AudioTimingControllerDialogue::Commit()
|
||||
{
|
||||
int new_start_ms = context->audioController->MillisecondsFromSamples(GetLeftMarker()->GetPosition());
|
||||
int new_end_ms = context->audioController->MillisecondsFromSamples(GetRightMarker()->GetPosition());
|
||||
int new_start_ms = context->audioController->MillisecondsFromSamples(*GetLeftMarker());
|
||||
int new_end_ms = context->audioController->MillisecondsFromSamples(*GetRightMarker());
|
||||
|
||||
// If auto committing is enabled, timing_modified will be true iif it is an
|
||||
// auto commit, as there is never pending changes to commit when the button
|
||||
|
@ -420,8 +407,6 @@ void AudioTimingControllerDialogue::Commit()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AudioTimingControllerDialogue::Revert()
|
||||
{
|
||||
if (AssDialogue *line = context->selectionController->GetActiveLine())
|
||||
|
@ -439,16 +424,13 @@ void AudioTimingControllerDialogue::Revert()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool AudioTimingControllerDialogue::IsNearbyMarker(int64_t sample, int sensitivity) const
|
||||
{
|
||||
SampleRange range(sample-sensitivity, sample+sensitivity);
|
||||
|
||||
return range.contains(markers[0].GetPosition()) || range.contains(markers[1].GetPosition());
|
||||
return range.contains(markers[0]) || range.contains(markers[1]);
|
||||
}
|
||||
|
||||
|
||||
AudioMarker * AudioTimingControllerDialogue::OnLeftClick(int64_t sample, int sensitivity)
|
||||
{
|
||||
assert(sensitivity >= 0);
|
||||
|
@ -458,8 +440,8 @@ AudioMarker * AudioTimingControllerDialogue::OnLeftClick(int64_t sample, int sen
|
|||
AudioMarkerDialogueTiming *left = GetLeftMarker();
|
||||
AudioMarkerDialogueTiming *right = GetRightMarker();
|
||||
|
||||
dist_l = tabs(left->GetPosition() - sample);
|
||||
dist_r = tabs(right->GetPosition() - sample);
|
||||
dist_l = tabs(*left - sample);
|
||||
dist_r = tabs(*right - sample);
|
||||
|
||||
if (dist_l < dist_r && dist_l <= sensitivity)
|
||||
{
|
||||
|
@ -483,8 +465,6 @@ AudioMarker * AudioTimingControllerDialogue::OnLeftClick(int64_t sample, int sen
|
|||
return right;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AudioMarker * AudioTimingControllerDialogue::OnRightClick(int64_t sample, int sensitivity)
|
||||
{
|
||||
AudioMarkerDialogueTiming *right = GetRightMarker();
|
||||
|
@ -492,20 +472,16 @@ AudioMarker * AudioTimingControllerDialogue::OnRightClick(int64_t sample, int se
|
|||
return right;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AudioTimingControllerDialogue::OnMarkerDrag(AudioMarker *marker, int64_t new_position)
|
||||
{
|
||||
assert(marker == &markers[0] || marker == &markers[1]);
|
||||
|
||||
SetMarker(static_cast<AudioMarkerDialogueTiming*>(marker), new_position);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AudioTimingControllerDialogue::UpdateSelection()
|
||||
{
|
||||
AnnounceUpdatedPrimaryRange();
|
||||
AnnounceUpdatedStyleRanges();
|
||||
}
|
||||
|
||||
void AudioTimingControllerDialogue::SetMarker(AudioMarkerDialogueTiming *marker, int64_t sample)
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "ass_file.h"
|
||||
#include "ass_karaoke.h"
|
||||
#include "audio_marker_provider_keyframes.h"
|
||||
#include "audio_renderer.h"
|
||||
#include "audio_timing.h"
|
||||
#include "include/aegisub/context.h"
|
||||
#include "main.h"
|
||||
|
@ -120,6 +121,7 @@ public:
|
|||
void GetMarkers(const SampleRange &range, AudioMarkerVector &out_markers) const;
|
||||
wxString GetWarningMessage() const { return ""; }
|
||||
SampleRange GetIdealVisibleSampleRange() const;
|
||||
void GetRenderingStyles(AudioRenderingStyleRanges &ranges) const;
|
||||
SampleRange GetPrimaryPlaybackRange() const;
|
||||
bool HasLabels() const { return true; }
|
||||
void GetLabels(const SampleRange &range, std::vector<AudioLabel> &out_labels) const;
|
||||
|
@ -199,6 +201,12 @@ void AudioTimingControllerKaraoke::Prev() {
|
|||
}
|
||||
}
|
||||
|
||||
void AudioTimingControllerKaraoke::GetRenderingStyles(AudioRenderingStyleRanges &ranges) const
|
||||
{
|
||||
SampleRange sr = GetPrimaryPlaybackRange();
|
||||
ranges.AddRange(sr.begin(), sr.end(), AudioStyle_Selected);
|
||||
}
|
||||
|
||||
SampleRange AudioTimingControllerKaraoke::GetPrimaryPlaybackRange() const {
|
||||
return SampleRange(
|
||||
cur_syl > 0 ? markers[cur_syl - 1] : start_marker,
|
||||
|
|
Loading…
Reference in a new issue