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:
Thomas Goyne 2011-11-18 22:56:45 +00:00
parent 262d5195c5
commit 8d28b44773
13 changed files with 279 additions and 198 deletions

View file

@ -336,17 +336,15 @@ void AudioController::SetTimingController(AudioTimingController *new_controller)
{ {
if (timing_controller.get() != new_controller) { if (timing_controller.get() != new_controller) {
timing_controller.reset(new_controller); timing_controller.reset(new_controller);
timing_controller->AddMarkerMovedListener(std::tr1::bind(std::tr1::ref(AnnounceMarkerMoved))); timing_controller->AddMarkerMovedListener(bind(std::tr1::ref(AnnounceMarkerMoved)));
timing_controller->AddLabelChangedListener(std::tr1::bind(std::tr1::ref(AnnounceLabelChanged))); timing_controller->AddLabelChangedListener(bind(std::tr1::ref(AnnounceLabelChanged)));
timing_controller->AddUpdatedPrimaryRangeListener(&AudioController::OnTimingControllerUpdatedPrimaryRange, this); timing_controller->AddUpdatedPrimaryRangeListener(&AudioController::OnTimingControllerUpdatedPrimaryRange, this);
timing_controller->AddUpdatedStyleRangesListener(&AudioController::OnTimingControllerUpdatedStyleRanges, this); timing_controller->AddUpdatedStyleRangesListener(bind(std::tr1::ref(AnnounceStyleRangesChanged)));
} }
AnnounceTimingControllerChanged(); AnnounceTimingControllerChanged();
} }
void AudioController::OnTimingControllerUpdatedPrimaryRange() void AudioController::OnTimingControllerUpdatedPrimaryRange()
{ {
if (playback_mode == PM_PrimaryRange) if (playback_mode == PM_PrimaryRange)
@ -357,12 +355,6 @@ void AudioController::OnTimingControllerUpdatedPrimaryRange()
AnnounceSelectionChanged(); AnnounceSelectionChanged();
} }
void AudioController::OnTimingControllerUpdatedStyleRanges()
{
/// @todo redraw and stuff, probably
}
void AudioController::OnSubtitlesSave() void AudioController::OnSubtitlesSave()
{ {
if (IsAudioOpen()) if (IsAudioOpen())

View file

@ -201,6 +201,9 @@ class AudioController : public wxEvtHandler, public AudioMarkerProvider, public
/// The selected time range changed /// The selected time range changed
agi::signal::Signal<> AnnounceSelectionChanged; agi::signal::Signal<> AnnounceSelectionChanged;
/// The styling ranges have been updated by the timing controller
agi::signal::Signal<> AnnounceStyleRangesChanged;
/// The audio output object /// The audio output object
AudioPlayer *player; AudioPlayer *player;
@ -390,6 +393,7 @@ public:
DEFINE_SIGNAL_ADDERS(AnnouncePlaybackStop, AddPlaybackStopListener) DEFINE_SIGNAL_ADDERS(AnnouncePlaybackStop, AddPlaybackStopListener)
DEFINE_SIGNAL_ADDERS(AnnounceTimingControllerChanged, AddTimingControllerListener) DEFINE_SIGNAL_ADDERS(AnnounceTimingControllerChanged, AddTimingControllerListener)
DEFINE_SIGNAL_ADDERS(AnnounceSelectionChanged, AddSelectionChangedListener) DEFINE_SIGNAL_ADDERS(AnnounceSelectionChanged, AddSelectionChangedListener)
DEFINE_SIGNAL_ADDERS(AnnounceStyleRangesChanged, AddStyleRangesChangedListener)
}; };
/// @class AudioMarker /// @class AudioMarker

View file

@ -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) AudioDisplay::AudioDisplay(wxWindow *parent, AudioController *controller, agi::Context *context)
: wxWindow(parent, -1, wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS|wxBORDER_SIMPLE) : 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)) , scrollbar(new AudioDisplayScrollbar(this))
, timeline(new AudioDisplayTimeline(this)) , timeline(new AudioDisplayTimeline(this))
, dragged_object(0) , dragged_object(0)
, old_selection(0, 0)
{ {
style_ranges[0] = AudioStyle_Normal;
scroll_left = 0; scroll_left = 0;
pixel_audio_width = 0; pixel_audio_width = 0;
scale_amplitude = 1.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->AddTimingControllerListener(&AudioDisplay::Refresh, this, true, (const wxRect*)0));
slots.push_back(controller->AddMarkerMovedListener(&AudioDisplay::OnMarkerMoved, this)); slots.push_back(controller->AddMarkerMovedListener(&AudioDisplay::OnMarkerMoved, this));
slots.push_back(controller->AddSelectionChangedListener(&AudioDisplay::OnSelectionChanged, this)); slots.push_back(controller->AddSelectionChangedListener(&AudioDisplay::OnSelectionChanged, this));
slots.push_back(controller->AddStyleRangesChangedListener(&AudioDisplay::OnStyleRangesChanged, this));
OPT_SUB("Audio/Spectrum", &AudioDisplay::ReloadRenderingSettings, this); OPT_SUB("Audio/Spectrum", &AudioDisplay::ReloadRenderingSettings, this);
@ -764,15 +812,9 @@ BEGIN_EVENT_TABLE(AudioDisplay, wxWindow)
EVT_SET_FOCUS(AudioDisplay::OnFocus) EVT_SET_FOCUS(AudioDisplay::OnFocus)
EVT_KILL_FOCUS(AudioDisplay::OnFocus) EVT_KILL_FOCUS(AudioDisplay::OnFocus)
EVT_KEY_DOWN(AudioDisplay::OnKeyDown) 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) void AudioDisplay::OnPaint(wxPaintEvent& event)
{ {
wxAutoBufferedPaintDC dc(this); wxAutoBufferedPaintDC dc(this);
@ -793,11 +835,6 @@ void AudioDisplay::OnPaint(wxPaintEvent& event)
bool redraw_scrollbar = false; bool redraw_scrollbar = false;
bool redraw_timeline = 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(); wxPoint client_org = GetClientAreaOrigin();
for (wxRegionIterator region(GetUpdateRegion()); region; ++region) for (wxRegionIterator region(GetUpdateRegion()); region; ++region)
{ {
@ -816,38 +853,31 @@ void AudioDisplay::OnPaint(wxPaintEvent& event)
continue; continue;
} }
// p1 -> p2 = before selection SampleRange updsamples(
// 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(
SamplesFromRelativeX(updrect.x - foot_size), SamplesFromRelativeX(updrect.x - foot_size),
SamplesFromRelativeX(updrect.x + updrect.width + 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 // Draw markers on top of it all
AudioMarkerVector markers; AudioMarkerVector markers;
controller->GetMarkers(updrectsamples, markers); controller->GetMarkers(updsamples, markers);
wxDCPenChanger pen_retainer(dc, wxPen()); wxDCPenChanger pen_retainer(dc, wxPen());
wxDCBrushChanger brush_retainer(dc, wxBrush()); wxDCBrushChanger brush_retainer(dc, wxBrush());
for (AudioMarkerVector::iterator marker_i = markers.begin(); marker_i != markers.end(); ++marker_i) for (AudioMarkerVector::iterator marker_i = markers.begin(); marker_i != markers.end(); ++marker_i)
@ -876,7 +906,7 @@ void AudioDisplay::OnPaint(wxPaintEvent& event)
// Draw labels // Draw labels
std::vector<AudioLabelProvider::AudioLabel> labels; std::vector<AudioLabelProvider::AudioLabel> labels;
controller->GetLabels(updrectsamples, labels); controller->GetLabels(updsamples, labels);
if (!labels.empty()) if (!labels.empty())
{ {
wxDCFontChanger fc(dc); wxDCFontChanger fc(dc);
@ -943,7 +973,7 @@ void AudioDisplay::OnPaint(wxPaintEvent& event)
track_cursor_label_rect.SetPosition(label_pos); track_cursor_label_rect.SetPosition(label_pos);
track_cursor_label_rect.SetSize(label_size); track_cursor_label_rect.SetSize(label_size);
if (need_extra_redraw) 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; int old_pos = track_cursor_pos;
track_cursor_pos = new_pos; track_cursor_pos = new_pos;
RefreshRect(wxRect(old_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)); RefreshRect(wxRect(new_pos - scroll_left - 0, audio_top, 1, audio_height), false);
// Make sure the old label gets cleared away // Make sure the old label gets cleared away
RefreshRect(track_cursor_label_rect); RefreshRect(track_cursor_label_rect, false);
if (show_time) 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))); new_label_time.SetMS(controller->MillisecondsFromSamples(SamplesFromAbsoluteX(track_cursor_pos)));
track_cursor_label = new_label_time.GetASSFormated(); track_cursor_label = new_label_time.GetASSFormated();
track_cursor_label_rect.x += new_pos - old_pos; track_cursor_label_rect.x += new_pos - old_pos;
RefreshRect(track_cursor_label_rect); RefreshRect(track_cursor_label_rect, false);
} }
else else
{ {
@ -1148,7 +1178,7 @@ void AudioDisplay::OnSize(wxSizeEvent &event)
void AudioDisplay::OnFocus(wxFocusEvent &event) void AudioDisplay::OnFocus(wxFocusEvent &event)
{ {
// The scrollbar indicates focus so repaint that // 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() void AudioDisplay::OnSelectionChanged()
{ {
/// @todo Handle rendering style ranges from timing controller instead
SampleRange sel(controller->GetPrimaryPlaybackRange()); SampleRange sel(controller->GetPrimaryPlaybackRange());
scrollbar->SetSelection(AbsoluteXFromSamples(sel.begin()), AbsoluteXFromSamples(sel.length())); scrollbar->SetSelection(AbsoluteXFromSamples(sel.begin()), AbsoluteXFromSamples(sel.length()));
if (OPT_GET("Audio/Auto/Scroll")->GetBool()) if (OPT_GET("Audio/Auto/Scroll")->GetBool())
{
ScrollSampleRangeInView(sel); 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(scrollbar->GetBounds(), false);
}
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())
{ {
RefreshRect(wxRect(std::min(e1, e2)-10, audio_top, abs(e1-e2)+20, audio_height)); 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 else
{ {
RefreshRect(wxRect(s1 - 10, audio_top, e1 + 20, audio_height)); if (old_style != new_style)
RefreshRect(wxRect(s2 - 10, audio_top, e2 + 20, audio_height)); Redraw(range_start, new_style_it->first);
new_style = new_style_it->second;
range_start = new_style_it->first;
++new_style_it;
}
} }
RefreshRect(scrollbar->GetBounds()); // Fill in the last style range
if (old_style != new_style)
{
Redraw(range_start, SamplesFromRelativeX(GetClientSize().GetWidth()));
}
}
old_selection = sel; 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() void AudioDisplay::OnMarkerMoved()
{ {
/// @todo investigate if it's worth refreshing only the changed spots /// @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);
} }

View file

@ -98,7 +98,7 @@ public:
/// timing controller. The audio display also renders audio according to the audio controller /// timing controller. The audio display also renders audio according to the audio controller
/// and the timing controller, using an audio renderer instance. /// and the timing controller, using an audio renderer instance.
class AudioDisplay: public wxWindow { class AudioDisplay: public wxWindow {
private:
std::list<agi::signal::Connection> slots; std::list<agi::signal::Connection> slots;
agi::Context *context; agi::Context *context;
@ -146,6 +146,8 @@ private:
/// Height of main audio area in pixels /// Height of main audio area in pixels
int audio_height; 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 /// Zoom level given as a number, see SetZoomLevel for details
int zoom_level; int zoom_level;
@ -163,8 +165,8 @@ private:
/// @brief Remove the tracking cursor from the display /// @brief Remove the tracking cursor from the display
void RemoveTrackCursor(); void RemoveTrackCursor();
/// Previous audio selection for optimizing redraw when selection changes /// Previous style ranges for optimizing redraw when ranges change
SampleRange old_selection; std::map<int64_t, int> style_ranges;
/// @brief Reload all rendering settings from Options and reset caches /// @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. /// in Options and need to be reloaded to take effect.
void ReloadRenderingSettings(); 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 /// wxWidgets paint event
void OnPaint(wxPaintEvent &event); void OnPaint(wxPaintEvent &event);
/// wxWidgets mouse input event /// wxWidgets mouse input event
@ -187,10 +194,10 @@ private:
void OnAudioOpen(AudioProvider *provider); void OnAudioOpen(AudioProvider *provider);
void OnPlaybackPosition(int64_t sample_position); void OnPlaybackPosition(int64_t sample_position);
void OnSelectionChanged(); void OnSelectionChanged();
void OnStyleRangesChanged();
void OnMarkerMoved(); void OnMarkerMoved();
public: public:
AudioDisplay(wxWindow *parent, AudioController *controller, agi::Context *context); AudioDisplay(wxWindow *parent, AudioController *controller, agi::Context *context);
~AudioDisplay(); ~AudioDisplay();

View file

@ -46,9 +46,12 @@
#include "audio_renderer.h" #include "audio_renderer.h"
#include "include/aegisub/audio_provider.h" #include "include/aegisub/audio_provider.h"
#undef min template<class C, class F> static void for_each(C &container, F const& func)
#undef max {
std::for_each(container.begin(), container.end(), func);
}
using std::tr1::placeholders::_1;
AudioRendererBitmapCacheBitmapFactory::AudioRendererBitmapCacheBitmapFactory(AudioRenderer *_renderer) AudioRendererBitmapCacheBitmapFactory::AudioRendererBitmapCacheBitmapFactory(AudioRenderer *_renderer)
{ {
@ -80,19 +83,18 @@ size_t AudioRendererBitmapCacheBitmapFactory::GetBlockSize() const
AudioRenderer::AudioRenderer() AudioRenderer::AudioRenderer()
: cache_bitmap_width(32) // arbitrary value for now : cache_bitmap_width(32) // arbitrary value for now
, bitmaps_normal(256, AudioRendererBitmapCacheBitmapFactory(this))
, bitmaps_selected(256, AudioRendererBitmapCacheBitmapFactory(this))
, cache_bitmap_maxsize(0) , cache_bitmap_maxsize(0)
, cache_renderer_maxsize(0) , cache_renderer_maxsize(0)
, renderer(0) , renderer(0)
, provider(0) , provider(0)
{ {
bitmaps.resize(AudioStyle_MAX, AudioRendererBitmapCache(256, AudioRendererBitmapCacheBitmapFactory(this)));
// Make sure there's *some* values for those fields, and in the caches // Make sure there's *some* values for those fields, and in the caches
SetSamplesPerPixel(1); SetSamplesPerPixel(1);
SetHeight(1); SetHeight(1);
} }
AudioRenderer::~AudioRenderer() AudioRenderer::~AudioRenderer()
{ {
// Nothing to do, everything is auto-allocated // 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); size_t rendered_width = (size_t)((provider->GetNumSamples() + pixel_samples - 1) / pixel_samples);
cache_numblocks = rendered_width / cache_bitmap_width; cache_numblocks = rendered_width / cache_bitmap_width;
bitmaps_normal.SetBlockCount(cache_numblocks); for_each(bitmaps, bind(&AudioRendererBitmapCache::SetBlockCount, _1, cache_numblocks));
bitmaps_selected.SetBlockCount(cache_numblocks);
} }
} }
wxBitmap AudioRenderer::GetCachedBitmap(int i, bool selected) wxBitmap AudioRenderer::GetCachedBitmap(int i, AudioRenderingStyle style)
{ {
assert(provider); assert(provider);
assert(renderer); assert(renderer);
// Pick the cache to use
AudioRendererBitmapCache *cache = selected ? &bitmaps_selected : &bitmaps_normal;
bool created = false; bool created = false;
wxBitmap *bmp = cache->Get(i, &created); wxBitmap *bmp = bitmaps[style].Get(i, &created);
assert(bmp); assert(bmp);
if (created) if (created)
{ {
renderer->Render(*bmp, i*cache_bitmap_width, selected); renderer->Render(*bmp, i*cache_bitmap_width, style);
} }
assert(bmp->IsOk()); 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); assert(start >= 0);
@ -257,7 +255,7 @@ void AudioRenderer::Render(wxDC &dc, wxPoint origin, int start, int length, bool
else if (firstbitmap == lastbitmap) else if (firstbitmap == lastbitmap)
{ {
const int renderwidth = lastbitmapoffset - firstbitmapoffset; const int renderwidth = lastbitmapoffset - firstbitmapoffset;
wxBitmap bmp = GetCachedBitmap(firstbitmap, selected); wxBitmap bmp = GetCachedBitmap(firstbitmap, style);
wxMemoryDC bmpdc(bmp); wxMemoryDC bmpdc(bmp);
dc.Blit(origin, wxSize(renderwidth, pixel_height), &bmpdc, wxPoint(firstbitmapoffset, 0)); dc.Blit(origin, wxSize(renderwidth, pixel_height), &bmpdc, wxPoint(firstbitmapoffset, 0));
origin.x += renderwidth; origin.x += renderwidth;
@ -267,7 +265,7 @@ void AudioRenderer::Render(wxDC &dc, wxPoint origin, int start, int length, bool
wxBitmap bmp; wxBitmap bmp;
{ {
bmp = GetCachedBitmap(firstbitmap, selected); bmp = GetCachedBitmap(firstbitmap, style);
// Can't use dc.DrawBitmap here because we need to clip the bitmap // Can't use dc.DrawBitmap here because we need to clip the bitmap
wxMemoryDC bmpdc(bmp); wxMemoryDC bmpdc(bmp);
dc.Blit(origin, wxSize(cache_bitmap_width-firstbitmapoffset, pixel_height), 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) for (int i = firstbitmap+1; i < lastbitmap; ++i)
{ {
bmp = GetCachedBitmap(i, selected); bmp = GetCachedBitmap(i, style);
dc.DrawBitmap(bmp, origin); dc.DrawBitmap(bmp, origin);
origin.x += cache_bitmap_width; origin.x += cache_bitmap_width;
} }
{ {
bmp = GetCachedBitmap(lastbitmap, selected); bmp = GetCachedBitmap(lastbitmap, style);
// We also need clipping here // We also need clipping here
wxMemoryDC bmpdc(bmp); wxMemoryDC bmpdc(bmp);
dc.Blit(origin, wxSize(lastbitmapoffset+1, pixel_height), &bmpdc, wxPoint(0, 0)); 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 // Now render blank audio from origin to end
if (origin.x < lastx) 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[style].Age(cache_bitmap_maxsize);
bitmaps_selected.Age(cache_bitmap_maxsize);
else
bitmaps_normal.Age(cache_bitmap_maxsize);
renderer->AgeCache(cache_renderer_maxsize); renderer->AgeCache(cache_renderer_maxsize);
} }
void AudioRenderer::Invalidate() void AudioRenderer::Invalidate()
{ {
bitmaps_normal.Age(0); for_each(bitmaps, bind(&AudioRendererBitmapCache::Age, _1, 0));
bitmaps_selected.Age(0);
} }
void AudioRendererBitmapProvider::SetProvider(AudioProvider *_provider) void AudioRendererBitmapProvider::SetProvider(AudioProvider *_provider)
{ {
if (provider == _provider) return; if (provider == _provider) return;
@ -342,4 +334,3 @@ void AudioRendererBitmapProvider::SetAmplitudeScale(float _amplitude_scale)
OnSetAmplitudeScale(); OnSetAmplitudeScale();
} }

View file

@ -38,6 +38,7 @@
#ifndef AGI_PRE #ifndef AGI_PRE
#include <memory> #include <memory>
#include <vector>
#include <wx/dc.h> #include <wx/dc.h>
#include <wx/gdicmn.h> #include <wx/gdicmn.h>
@ -52,6 +53,41 @@ class AudioProvider;
class AudioRendererBitmapProvider; class AudioRendererBitmapProvider;
class AudioRenderer; 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 /// @class AudioRendererBitmapCacheBitmapFactory
/// @brief Produces wxBitmap objects for DataBlockCache storage for the audio renderer /// @brief Produces wxBitmap objects for DataBlockCache storage for the audio renderer
struct AudioRendererBitmapCacheBitmapFactory { struct AudioRendererBitmapCacheBitmapFactory {
@ -104,10 +140,8 @@ class AudioRenderer {
/// Width of bitmaps to store in cache /// Width of bitmaps to store in cache
const int cache_bitmap_width; const int cache_bitmap_width;
/// Cached bitmaps for normal audio ranges /// Cached bitmaps for audio ranges
AudioRendererBitmapCache bitmaps_normal; std::vector<AudioRendererBitmapCache> bitmaps;
/// Cached bitmaps for marked (selected) audio ranges
AudioRendererBitmapCache bitmaps_selected;
/// Number of blocks in the bitmap caches /// Number of blocks in the bitmap caches
size_t cache_numblocks; size_t cache_numblocks;
/// The maximum allowed size of each bitmap cache, in bytes /// The maximum allowed size of each bitmap cache, in bytes
@ -123,12 +157,12 @@ class AudioRenderer {
/// @brief Make sure bitmap index i is in cache /// @brief Make sure bitmap index i is in cache
/// @param i Index of bitmap to get into cache /// @param i Index of bitmap to get into cache
/// @param selected Whether to get a "selected" state bitmap or not /// @param style Rendering style required for bitmap
/// @return The requested bitmap /// @return The requested bitmap
/// ///
/// Will attempt retrieving the requested bitmap from the cache, creating it /// Will attempt retrieving the requested bitmap from the cache, creating it
/// if the cache doesn't have 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 /// @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 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 start First pixel from beginning of the audio stream to render
/// @param length Number of pixels of audio 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 /// The first audio sample rendered is start*pixel_samples, and the number
/// of audio samples rendered is length*pixel_samples. /// 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 /// @brief Invalidate all cached data
/// ///
@ -286,20 +320,20 @@ public:
/// @brief Rendering function /// @brief Rendering function
/// @param bmp Bitmap to render to /// @param bmp Bitmap to render to
/// @param start First pixel from beginning of the audio stream to render /// @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 style Style to render audio in
/// ///
/// Deriving classes must implement this method. The bitmap in bmp holds /// Deriving classes must implement this method. The bitmap in bmp holds
/// the width and height to render. /// 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 /// @brief Blank audio rendering function
/// @param dc The device context to render to /// @param dc The device context to render to
/// @param rect The rectangle to fill with the image of blank audio /// @param rect The rectangle to fill with the image of blank audio
/// @param selected Whether to render as being selected or not /// @param style Style to render audio in
/// ///
/// Deriving classes must implement this method. The rectangle has the height /// Deriving classes must implement this method. The rectangle has the height
/// of the entire canvas the audio is being rendered in. /// 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 /// @brief Change audio provider
/// @param provider Audio provider to change to /// @param provider Audio provider to change to

View file

@ -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) if (!cache)
return; return;
@ -284,7 +284,7 @@ void AudioSpectrumRenderer::Render(wxBitmap &bmp, int start, bool selected)
ptrdiff_t stride = img.GetWidth()*3; ptrdiff_t stride = img.GetWidth()*3;
int imgheight = img.GetHeight(); 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 /// @todo Make minband and maxband configurable
int minband = 0; 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 // 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]; unsigned char color_raw[4];
pal->map(0.0, color_raw); pal->map(0.0, color_raw);
wxColour col(color_raw[0], color_raw[1], color_raw[2]); wxColour col(color_raw[0], color_raw[1], color_raw[2]);

View file

@ -117,11 +117,11 @@ public:
/// @brief Render a range of audio spectrum /// @brief Render a range of audio spectrum
/// @param bmp [in,out] Bitmap to render into, also carries lenght information /// @param bmp [in,out] Bitmap to render into, also carries lenght information
/// @param start First column of pixel data in display to render /// @param start First column of pixel data in display to render
/// @param selected Whether to use the alternate colour scheme /// @param style Style to render audio in
void Render(wxBitmap &bmp, int start, bool selected); void Render(wxBitmap &bmp, int start, AudioRenderingStyle style);
/// @brief Render blank area /// @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 /// @brief Set the derivation resolution
/// @param derivation_size Binary logarithm of number of samples to use in deriving frequency-power data /// @param derivation_size Binary logarithm of number of samples to use in deriving frequency-power data

View file

@ -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); wxMemoryDC dc(bmp);
wxRect rect(wxPoint(0, 0), bmp.GetSize()); wxRect rect(wxPoint(0, 0), bmp.GetSize());
int midpoint = rect.height / 2; int midpoint = rect.height / 2;
AudioColorScheme *pal = selected ? &colors_selected : &colors_normal; AudioColorScheme *pal = style == AudioStyle_Selected ? &colors_selected : &colors_normal;
// Fill the background // Fill the background
dc.SetBrush(wxBrush(pal->get(0.0f))); 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 line(pal->get(1.0));
wxColor bg(pal->get(0.0)); wxColor bg(pal->get(0.0));

View file

@ -63,11 +63,11 @@ public:
/// @brief Render a range of audio waveform /// @brief Render a range of audio waveform
/// @param bmp [in,out] Bitmap to render into, also carries lenght information /// @param bmp [in,out] Bitmap to render into, also carries lenght information
/// @param start First column of pixel data in display to render /// @param start First column of pixel data in display to render
/// @param selected Whether to use the alternate colour scheme /// @param style Style to render audio in
void Render(wxBitmap &bmp, int start, bool selected); void Render(wxBitmap &bmp, int start, AudioRenderingStyle style);
/// @brief Render blank area /// @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 /// @brief Cleans up the cache
/// @param max_size Maximum size in bytes for the cache /// @param max_size Maximum size in bytes for the cache

View file

@ -36,6 +36,7 @@
class AssDialogue; class AssDialogue;
class AssFile; class AssFile;
class AssKaraoke; class AssKaraoke;
class AudioRenderingStyleRanges;
namespace agi { struct Context; } namespace agi { struct Context; }
#include "audio_controller.h" #include "audio_controller.h"
@ -79,6 +80,10 @@ public:
/// currently. /// currently.
virtual SampleRange GetPrimaryPlaybackRange() const = 0; 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? /// @brief Does this timing mode have labels on the audio display?
/// @return True if this timing mode needs labels on the audio display. /// @return True if this timing mode needs labels on the audio display.
/// ///

View file

@ -44,6 +44,7 @@
#include "ass_time.h" #include "ass_time.h"
#include "audio_controller.h" #include "audio_controller.h"
#include "audio_marker_provider_keyframes.h" #include "audio_marker_provider_keyframes.h"
#include "audio_renderer.h"
#include "audio_timing.h" #include "audio_timing.h"
#include "include/aegisub/context.h" #include "include/aegisub/context.h"
#include "main.h" #include "main.h"
@ -106,8 +107,10 @@ public:
/// This checks that the markers aren't already part of a pair, and then /// This checks that the markers aren't already part of a pair, and then
/// sets their "other" field. Positions and styles aren't affected. /// sets their "other" field. Positions and styles aren't affected.
static void InitPair(AudioMarkerDialogueTiming *marker1, AudioMarkerDialogueTiming *marker2); static void InitPair(AudioMarkerDialogueTiming *marker1, AudioMarkerDialogueTiming *marker2);
};
/// Implicit decay to the position of the marker
operator int64_t() const { return position; }
};
/// @class AudioTimingControllerDialogue /// @class AudioTimingControllerDialogue
@ -176,6 +179,7 @@ public:
wxString GetWarningMessage() const; wxString GetWarningMessage() const;
SampleRange GetIdealVisibleSampleRange() const; SampleRange GetIdealVisibleSampleRange() const;
SampleRange GetPrimaryPlaybackRange() const; SampleRange GetPrimaryPlaybackRange() const;
void GetRenderingStyles(AudioRenderingStyleRanges &ranges) const;
bool HasLabels() const { return false; } bool HasLabels() const { return false; }
void GetLabels(SampleRange const& range, std::vector<AudioLabel> &out) const { } void GetLabels(SampleRange const& range, std::vector<AudioLabel> &out) const { }
void Next(); void Next();
@ -195,8 +199,6 @@ public:
~AudioTimingControllerDialogue(); ~AudioTimingControllerDialogue();
}; };
AudioTimingController *CreateDialogueTimingController(agi::Context *c) AudioTimingController *CreateDialogueTimingController(agi::Context *c)
{ {
return new AudioTimingControllerDialogue(c); return new AudioTimingControllerDialogue(c);
@ -226,7 +228,6 @@ void AudioMarkerDialogueTiming::SetPosition(int64_t new_position)
} }
} }
AudioMarkerDialogueTiming::AudioMarkerDialogueTiming() AudioMarkerDialogueTiming::AudioMarkerDialogueTiming()
: other(0) : other(0)
, position(0) , position(0)
@ -238,7 +239,6 @@ AudioMarkerDialogueTiming::AudioMarkerDialogueTiming()
// Nothing more to do // Nothing more to do
} }
void AudioMarkerDialogueTiming::InitPair(AudioMarkerDialogueTiming *marker1, AudioMarkerDialogueTiming *marker2) void AudioMarkerDialogueTiming::InitPair(AudioMarkerDialogueTiming *marker1, AudioMarkerDialogueTiming *marker2)
{ {
assert(marker1->other == 0); assert(marker1->other == 0);
@ -248,8 +248,6 @@ void AudioMarkerDialogueTiming::InitPair(AudioMarkerDialogueTiming *marker1, Aud
marker2->other = marker1; marker2->other = marker1;
} }
// AudioTimingControllerDialogue // AudioTimingControllerDialogue
AudioTimingControllerDialogue::AudioTimingControllerDialogue(agi::Context *c) AudioTimingControllerDialogue::AudioTimingControllerDialogue(agi::Context *c)
@ -279,35 +277,31 @@ AudioTimingControllerDialogue::~AudioTimingControllerDialogue()
context->selectionController->RemoveSelectionListener(this); context->selectionController->RemoveSelectionListener(this);
} }
AudioMarkerDialogueTiming *AudioTimingControllerDialogue::GetLeftMarker() 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 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() 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 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 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]); out_markers.push_back(&markers[0]);
if (range.contains(markers[1].GetPosition())) if (range.contains(markers[1]))
out_markers.push_back(&markers[1]); out_markers.push_back(&markers[1]);
keyframes_provider.GetMarkers(range, out_markers); keyframes_provider.GetMarkers(range, out_markers);
@ -331,49 +325,42 @@ void AudioTimingControllerDialogue::OnFileChanged(int type) {
} }
} }
wxString AudioTimingControllerDialogue::GetWarningMessage() const wxString AudioTimingControllerDialogue::GetWarningMessage() const
{ {
// We have no warning messages currently, maybe add the old "Modified" message back later? // We have no warning messages currently, maybe add the old "Modified" message back later?
return wxString(); return wxString();
} }
SampleRange AudioTimingControllerDialogue::GetIdealVisibleSampleRange() const SampleRange AudioTimingControllerDialogue::GetIdealVisibleSampleRange() const
{ {
return GetPrimaryPlaybackRange(); return GetPrimaryPlaybackRange();
} }
SampleRange AudioTimingControllerDialogue::GetPrimaryPlaybackRange() const SampleRange AudioTimingControllerDialogue::GetPrimaryPlaybackRange() const
{ {
return SampleRange( return SampleRange(*GetLeftMarker(), *GetRightMarker());
GetLeftMarker()->GetPosition(),
GetRightMarker()->GetPosition());
} }
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() void AudioTimingControllerDialogue::Next()
{ {
context->selectionController->NextLine(); context->selectionController->NextLine();
} }
void AudioTimingControllerDialogue::Prev() void AudioTimingControllerDialogue::Prev()
{ {
context->selectionController->PrevLine(); context->selectionController->PrevLine();
} }
void AudioTimingControllerDialogue::Commit() void AudioTimingControllerDialogue::Commit()
{ {
int new_start_ms = context->audioController->MillisecondsFromSamples(GetLeftMarker()->GetPosition()); int new_start_ms = context->audioController->MillisecondsFromSamples(*GetLeftMarker());
int new_end_ms = context->audioController->MillisecondsFromSamples(GetRightMarker()->GetPosition()); int new_end_ms = context->audioController->MillisecondsFromSamples(*GetRightMarker());
// If auto committing is enabled, timing_modified will be true iif it is an // 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 // auto commit, as there is never pending changes to commit when the button
@ -420,8 +407,6 @@ void AudioTimingControllerDialogue::Commit()
} }
} }
void AudioTimingControllerDialogue::Revert() void AudioTimingControllerDialogue::Revert()
{ {
if (AssDialogue *line = context->selectionController->GetActiveLine()) if (AssDialogue *line = context->selectionController->GetActiveLine())
@ -439,16 +424,13 @@ void AudioTimingControllerDialogue::Revert()
} }
} }
bool AudioTimingControllerDialogue::IsNearbyMarker(int64_t sample, int sensitivity) const bool AudioTimingControllerDialogue::IsNearbyMarker(int64_t sample, int sensitivity) const
{ {
SampleRange range(sample-sensitivity, sample+sensitivity); SampleRange range(sample-sensitivity, sample+sensitivity);
return range.contains(markers[0].GetPosition()) || range.contains(markers[1].GetPosition()); return range.contains(markers[0]) || range.contains(markers[1]);
} }
AudioMarker * AudioTimingControllerDialogue::OnLeftClick(int64_t sample, int sensitivity) AudioMarker * AudioTimingControllerDialogue::OnLeftClick(int64_t sample, int sensitivity)
{ {
assert(sensitivity >= 0); assert(sensitivity >= 0);
@ -458,8 +440,8 @@ AudioMarker * AudioTimingControllerDialogue::OnLeftClick(int64_t sample, int sen
AudioMarkerDialogueTiming *left = GetLeftMarker(); AudioMarkerDialogueTiming *left = GetLeftMarker();
AudioMarkerDialogueTiming *right = GetRightMarker(); AudioMarkerDialogueTiming *right = GetRightMarker();
dist_l = tabs(left->GetPosition() - sample); dist_l = tabs(*left - sample);
dist_r = tabs(right->GetPosition() - sample); dist_r = tabs(*right - sample);
if (dist_l < dist_r && dist_l <= sensitivity) if (dist_l < dist_r && dist_l <= sensitivity)
{ {
@ -483,8 +465,6 @@ AudioMarker * AudioTimingControllerDialogue::OnLeftClick(int64_t sample, int sen
return right; return right;
} }
AudioMarker * AudioTimingControllerDialogue::OnRightClick(int64_t sample, int sensitivity) AudioMarker * AudioTimingControllerDialogue::OnRightClick(int64_t sample, int sensitivity)
{ {
AudioMarkerDialogueTiming *right = GetRightMarker(); AudioMarkerDialogueTiming *right = GetRightMarker();
@ -492,20 +472,16 @@ AudioMarker * AudioTimingControllerDialogue::OnRightClick(int64_t sample, int se
return right; return right;
} }
void AudioTimingControllerDialogue::OnMarkerDrag(AudioMarker *marker, int64_t new_position) void AudioTimingControllerDialogue::OnMarkerDrag(AudioMarker *marker, int64_t new_position)
{ {
assert(marker == &markers[0] || marker == &markers[1]); assert(marker == &markers[0] || marker == &markers[1]);
SetMarker(static_cast<AudioMarkerDialogueTiming*>(marker), new_position); SetMarker(static_cast<AudioMarkerDialogueTiming*>(marker), new_position);
} }
void AudioTimingControllerDialogue::UpdateSelection() void AudioTimingControllerDialogue::UpdateSelection()
{ {
AnnounceUpdatedPrimaryRange(); AnnounceUpdatedPrimaryRange();
AnnounceUpdatedStyleRanges();
} }
void AudioTimingControllerDialogue::SetMarker(AudioMarkerDialogueTiming *marker, int64_t sample) void AudioTimingControllerDialogue::SetMarker(AudioMarkerDialogueTiming *marker, int64_t sample)

View file

@ -29,6 +29,7 @@
#include "ass_file.h" #include "ass_file.h"
#include "ass_karaoke.h" #include "ass_karaoke.h"
#include "audio_marker_provider_keyframes.h" #include "audio_marker_provider_keyframes.h"
#include "audio_renderer.h"
#include "audio_timing.h" #include "audio_timing.h"
#include "include/aegisub/context.h" #include "include/aegisub/context.h"
#include "main.h" #include "main.h"
@ -120,6 +121,7 @@ public:
void GetMarkers(const SampleRange &range, AudioMarkerVector &out_markers) const; void GetMarkers(const SampleRange &range, AudioMarkerVector &out_markers) const;
wxString GetWarningMessage() const { return ""; } wxString GetWarningMessage() const { return ""; }
SampleRange GetIdealVisibleSampleRange() const; SampleRange GetIdealVisibleSampleRange() const;
void GetRenderingStyles(AudioRenderingStyleRanges &ranges) const;
SampleRange GetPrimaryPlaybackRange() const; SampleRange GetPrimaryPlaybackRange() const;
bool HasLabels() const { return true; } bool HasLabels() const { return true; }
void GetLabels(const SampleRange &range, std::vector<AudioLabel> &out_labels) const; 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 { SampleRange AudioTimingControllerKaraoke::GetPrimaryPlaybackRange() const {
return SampleRange( return SampleRange(
cur_syl > 0 ? markers[cur_syl - 1] : start_marker, cur_syl > 0 ? markers[cur_syl - 1] : start_marker,