2011-09-28 21:44:07 +02:00
|
|
|
// Copyright (c) 2011, Thomas Goyne <plorkyeran@aegisub.org>
|
|
|
|
//
|
|
|
|
// Permission to use, copy, modify, and distribute this software for any
|
|
|
|
// purpose with or without fee is hereby granted, provided that the above
|
|
|
|
// copyright notice and this permission notice appear in all copies.
|
|
|
|
//
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
//
|
|
|
|
// Aegisub Project http://www.aegisub.org/
|
|
|
|
|
|
|
|
/// @file audio_timing_karaoke.cpp
|
|
|
|
/// @brief Timing mode for karaoke
|
|
|
|
/// @ingroup audio_ui
|
|
|
|
///
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <libaegisub/signal.h>
|
|
|
|
|
|
|
|
#include "ass_dialogue.h"
|
|
|
|
#include "ass_file.h"
|
|
|
|
#include "ass_karaoke.h"
|
2012-02-02 00:59:12 +01:00
|
|
|
#include "audio_controller.h"
|
2011-11-18 23:56:45 +01:00
|
|
|
#include "audio_renderer.h"
|
2011-09-28 21:44:07 +02:00
|
|
|
#include "audio_timing.h"
|
|
|
|
#include "include/aegisub/context.h"
|
|
|
|
#include "main.h"
|
2011-10-19 06:19:01 +02:00
|
|
|
#include "pen.h"
|
2011-09-28 21:44:07 +02:00
|
|
|
#include "utils.h"
|
|
|
|
|
|
|
|
#ifndef AGI_PRE
|
|
|
|
#include <deque>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/// @class KaraokeMarker
|
|
|
|
/// @brief AudioMarker implementation for AudioTimingControllerKaraoke
|
|
|
|
class KaraokeMarker : public AudioMarker {
|
2012-02-02 00:58:58 +01:00
|
|
|
int position;
|
2011-10-19 06:19:01 +02:00
|
|
|
Pen *pen;
|
2011-09-28 21:44:07 +02:00
|
|
|
FeetStyle style;
|
|
|
|
public:
|
|
|
|
|
2012-02-02 00:58:58 +01:00
|
|
|
int GetPosition() const { return position; }
|
2011-09-28 21:44:07 +02:00
|
|
|
wxPen GetStyle() const { return *pen; }
|
|
|
|
FeetStyle GetFeet() const { return style; }
|
|
|
|
bool CanSnap() const { return false; }
|
|
|
|
|
2012-02-02 00:58:58 +01:00
|
|
|
void Move(int new_pos) { position = new_pos; }
|
2011-09-28 21:44:07 +02:00
|
|
|
|
2012-02-02 00:58:58 +01:00
|
|
|
KaraokeMarker(int position, Pen *pen, FeetStyle style)
|
2011-09-28 21:44:07 +02:00
|
|
|
: position(position)
|
|
|
|
, pen(pen)
|
|
|
|
, style(style)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-10-15 06:37:14 +02:00
|
|
|
KaraokeMarker(int position)
|
|
|
|
: position(position)
|
|
|
|
, pen(0)
|
|
|
|
, style(Feet_None)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-02-02 00:58:58 +01:00
|
|
|
operator int() const { return position; }
|
2011-09-28 21:44:07 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/// @class AudioTimingControllerKaraoke
|
|
|
|
/// @brief Karaoke timing mode for timing subtitles
|
|
|
|
///
|
|
|
|
/// Displays the active line with draggable markers between each pair of
|
|
|
|
/// adjacent syllables, along with the text of each syllable.
|
|
|
|
///
|
|
|
|
/// This does not support \kt, as it inherently requires that the end time of
|
|
|
|
/// one syllable be the same as the start time of the next one.
|
|
|
|
class AudioTimingControllerKaraoke : public AudioTimingController {
|
|
|
|
std::deque<agi::signal::Connection> slots;
|
|
|
|
agi::signal::Connection& file_changed_slot;
|
|
|
|
|
|
|
|
agi::Context *c; ///< Project context
|
|
|
|
AssDialogue *active_line; ///< Currently active line
|
|
|
|
AssKaraoke *kara; ///< Parsed karaoke model provided by karaoke controller
|
|
|
|
|
|
|
|
size_t cur_syl; ///< Index of currently selected syllable in the line
|
|
|
|
|
|
|
|
/// Pen used for the mid-syllable markers
|
2011-10-19 06:19:01 +02:00
|
|
|
Pen separator_pen;
|
2011-09-28 21:44:07 +02:00
|
|
|
/// Pen used for the start-of-line marker
|
2011-10-19 06:19:01 +02:00
|
|
|
Pen start_pen;
|
2011-09-28 21:44:07 +02:00
|
|
|
/// Pen used for the end-of-line marker
|
2011-10-19 06:19:01 +02:00
|
|
|
Pen end_pen;
|
2011-09-28 21:44:07 +02:00
|
|
|
|
|
|
|
/// Immobile marker for the beginning of the line
|
|
|
|
KaraokeMarker start_marker;
|
|
|
|
/// Immobile marker for the end of the line
|
|
|
|
KaraokeMarker end_marker;
|
|
|
|
/// Mobile markers between each pair of syllables
|
|
|
|
std::vector<KaraokeMarker> markers;
|
|
|
|
|
2011-11-16 20:56:00 +01:00
|
|
|
/// Marker provider for video keyframes
|
|
|
|
AudioMarkerProviderKeyframes keyframes_provider;
|
|
|
|
|
2012-02-02 00:59:12 +01:00
|
|
|
/// Marker provider for video playback position
|
|
|
|
VideoPositionMarkerProvider video_position_provider;
|
|
|
|
|
2011-09-28 21:44:07 +02:00
|
|
|
/// Labels containing the stripped text of each syllable
|
|
|
|
std::vector<AudioLabel> labels;
|
|
|
|
|
|
|
|
bool auto_commit; ///< Should changes be automatically commited?
|
|
|
|
int commit_id; ///< Last commit id used for an autocommit
|
2012-11-03 23:40:54 +01:00
|
|
|
bool pending_changes; ///< Are there any pending changes to be committed?
|
2011-09-28 21:44:07 +02:00
|
|
|
|
|
|
|
void OnAutoCommitChange(agi::OptionValue const& opt);
|
|
|
|
|
|
|
|
void DoCommit();
|
2012-02-22 23:00:54 +01:00
|
|
|
void ApplyLead(bool announce_primary);
|
2012-07-14 15:35:15 +02:00
|
|
|
int MoveMarker(KaraokeMarker *marker, int new_position);
|
|
|
|
void AnnounceChanges(int syl);
|
2011-09-28 21:44:07 +02:00
|
|
|
|
|
|
|
public:
|
|
|
|
// AudioTimingController implementation
|
2012-02-02 00:58:58 +01:00
|
|
|
void GetMarkers(const TimeRange &range, AudioMarkerVector &out_markers) const;
|
2011-09-28 21:44:07 +02:00
|
|
|
wxString GetWarningMessage() const { return ""; }
|
2012-02-02 00:58:58 +01:00
|
|
|
TimeRange GetIdealVisibleTimeRange() const;
|
2011-11-18 23:56:45 +01:00
|
|
|
void GetRenderingStyles(AudioRenderingStyleRanges &ranges) const;
|
2012-02-02 00:58:58 +01:00
|
|
|
TimeRange GetPrimaryPlaybackRange() const;
|
2012-10-05 01:15:45 +02:00
|
|
|
TimeRange GetActiveLineRange() const;
|
2012-02-02 00:58:58 +01:00
|
|
|
void GetLabels(const TimeRange &range, std::vector<AudioLabel> &out_labels) const;
|
2012-04-27 21:07:07 +02:00
|
|
|
void Next(NextMode mode);
|
2011-09-28 21:44:07 +02:00
|
|
|
void Prev();
|
|
|
|
void Commit();
|
|
|
|
void Revert();
|
2012-02-22 23:00:54 +01:00
|
|
|
void AddLeadIn();
|
|
|
|
void AddLeadOut();
|
2012-07-14 15:35:15 +02:00
|
|
|
void ModifyLength(int delta, bool shift_following);
|
|
|
|
void ModifyStart(int delta);
|
2012-02-02 00:58:58 +01:00
|
|
|
bool IsNearbyMarker(int ms, int sensitivity) const;
|
2012-02-10 01:04:13 +01:00
|
|
|
std::vector<AudioMarker*> OnLeftClick(int ms, bool, int sensitivity, int);
|
2012-10-16 23:08:20 +02:00
|
|
|
std::vector<AudioMarker*> OnRightClick(int ms, bool, int, int);
|
2012-02-10 01:04:13 +01:00
|
|
|
void OnMarkerDrag(std::vector<AudioMarker*> const& marker, int new_position, int);
|
2011-09-28 21:44:07 +02:00
|
|
|
|
|
|
|
AudioTimingControllerKaraoke(agi::Context *c, AssKaraoke *kara, agi::signal::Connection& file_changed);
|
|
|
|
};
|
|
|
|
|
|
|
|
AudioTimingController *CreateKaraokeTimingController(agi::Context *c, AssKaraoke *kara, agi::signal::Connection& file_changed)
|
|
|
|
{
|
|
|
|
return new AudioTimingControllerKaraoke(c, kara, file_changed);
|
|
|
|
}
|
|
|
|
|
|
|
|
AudioTimingControllerKaraoke::AudioTimingControllerKaraoke(agi::Context *c, AssKaraoke *kara, agi::signal::Connection& file_changed)
|
|
|
|
: file_changed_slot(file_changed)
|
|
|
|
, c(c)
|
|
|
|
, active_line(c->selectionController->GetActiveLine())
|
|
|
|
, kara(kara)
|
|
|
|
, cur_syl(0)
|
2011-10-19 06:19:01 +02:00
|
|
|
, separator_pen("Colour/Audio Display/Syllable Boundaries", "Audio/Line Boundaries Thickness", wxPENSTYLE_DOT)
|
|
|
|
, start_pen("Colour/Audio Display/Line boundary Start", "Audio/Line Boundaries Thickness")
|
|
|
|
, end_pen("Colour/Audio Display/Line boundary End", "Audio/Line Boundaries Thickness")
|
2012-02-02 00:58:58 +01:00
|
|
|
, start_marker(active_line->Start, &start_pen, AudioMarker::Feet_Right)
|
|
|
|
, end_marker(active_line->End, &end_pen, AudioMarker::Feet_Left)
|
2011-11-16 20:56:09 +01:00
|
|
|
, keyframes_provider(c, "Audio/Display/Draw/Keyframes in Karaoke Mode")
|
2012-02-02 00:59:12 +01:00
|
|
|
, video_position_provider(c)
|
2011-09-28 21:44:07 +02:00
|
|
|
, auto_commit(OPT_GET("Audio/Auto/Commit")->GetBool())
|
|
|
|
, commit_id(-1)
|
|
|
|
{
|
|
|
|
slots.push_back(kara->AddSyllablesChangedListener(&AudioTimingControllerKaraoke::Revert, this));
|
|
|
|
slots.push_back(OPT_SUB("Audio/Auto/Commit", &AudioTimingControllerKaraoke::OnAutoCommitChange, this));
|
|
|
|
|
2012-09-25 01:35:27 +02:00
|
|
|
keyframes_provider.AddMarkerMovedListener(std::bind(std::ref(AnnounceMarkerMoved)));
|
|
|
|
video_position_provider.AddMarkerMovedListener(std::bind(std::ref(AnnounceMarkerMoved)));
|
2011-11-16 20:56:00 +01:00
|
|
|
|
2011-09-28 21:44:07 +02:00
|
|
|
Revert();
|
2012-03-25 06:05:06 +02:00
|
|
|
|
2011-09-28 21:44:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void AudioTimingControllerKaraoke::OnAutoCommitChange(agi::OptionValue const& opt) {
|
|
|
|
auto_commit = opt.GetBool();
|
|
|
|
}
|
|
|
|
|
2012-04-27 21:07:07 +02:00
|
|
|
void AudioTimingControllerKaraoke::Next(NextMode mode) {
|
|
|
|
// Don't create new lines since it's almost never useful to k-time a line
|
|
|
|
// before dialogue timing it
|
|
|
|
if (mode != TIMING_UNIT)
|
|
|
|
cur_syl = markers.size();
|
2011-09-28 21:44:07 +02:00
|
|
|
|
|
|
|
++cur_syl;
|
|
|
|
if (cur_syl > markers.size()) {
|
|
|
|
--cur_syl;
|
|
|
|
c->selectionController->NextLine();
|
|
|
|
}
|
2011-11-18 23:58:22 +01:00
|
|
|
else {
|
2011-09-28 21:44:07 +02:00
|
|
|
AnnounceUpdatedPrimaryRange();
|
2011-11-18 23:58:22 +01:00
|
|
|
AnnounceUpdatedStyleRanges();
|
|
|
|
}
|
2012-01-22 18:15:25 +01:00
|
|
|
|
|
|
|
c->audioController->PlayPrimaryRange();
|
2011-09-28 21:44:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void AudioTimingControllerKaraoke::Prev() {
|
|
|
|
if (cur_syl == 0) {
|
|
|
|
AssDialogue *old_line = active_line;
|
|
|
|
c->selectionController->PrevLine();
|
|
|
|
if (old_line != active_line) {
|
|
|
|
cur_syl = markers.size();
|
|
|
|
AnnounceUpdatedPrimaryRange();
|
2011-11-18 23:58:22 +01:00
|
|
|
AnnounceUpdatedStyleRanges();
|
2011-09-28 21:44:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
--cur_syl;
|
|
|
|
AnnounceUpdatedPrimaryRange();
|
2011-11-18 23:58:22 +01:00
|
|
|
AnnounceUpdatedStyleRanges();
|
2011-09-28 21:44:07 +02:00
|
|
|
}
|
2012-01-22 18:15:25 +01:00
|
|
|
|
|
|
|
c->audioController->PlayPrimaryRange();
|
2011-09-28 21:44:07 +02:00
|
|
|
}
|
|
|
|
|
2011-11-18 23:56:45 +01:00
|
|
|
void AudioTimingControllerKaraoke::GetRenderingStyles(AudioRenderingStyleRanges &ranges) const
|
|
|
|
{
|
2012-02-02 00:58:58 +01:00
|
|
|
TimeRange sr = GetPrimaryPlaybackRange();
|
2012-02-17 01:14:45 +01:00
|
|
|
ranges.AddRange(sr.begin(), sr.end(), AudioStyle_Primary);
|
2012-03-12 01:07:22 +01:00
|
|
|
ranges.AddRange(start_marker, end_marker, AudioStyle_Selected);
|
2011-11-18 23:56:45 +01:00
|
|
|
}
|
|
|
|
|
2012-02-02 00:58:58 +01:00
|
|
|
TimeRange AudioTimingControllerKaraoke::GetPrimaryPlaybackRange() const {
|
|
|
|
return TimeRange(
|
2011-09-28 21:44:07 +02:00
|
|
|
cur_syl > 0 ? markers[cur_syl - 1] : start_marker,
|
|
|
|
cur_syl < markers.size() ? markers[cur_syl] : end_marker);
|
|
|
|
}
|
|
|
|
|
2012-10-05 01:15:45 +02:00
|
|
|
TimeRange AudioTimingControllerKaraoke::GetActiveLineRange() const {
|
2012-02-02 00:58:58 +01:00
|
|
|
return TimeRange(start_marker, end_marker);
|
2011-09-28 21:44:07 +02:00
|
|
|
}
|
|
|
|
|
2012-10-05 01:15:45 +02:00
|
|
|
TimeRange AudioTimingControllerKaraoke::GetIdealVisibleTimeRange() const {
|
|
|
|
return GetActiveLineRange();
|
|
|
|
}
|
|
|
|
|
2012-02-02 00:58:58 +01:00
|
|
|
void AudioTimingControllerKaraoke::GetMarkers(TimeRange const& range, AudioMarkerVector &out) const {
|
2011-09-28 21:44:07 +02:00
|
|
|
size_t i;
|
|
|
|
for (i = 0; i < markers.size() && markers[i] < range.begin(); ++i) ;
|
|
|
|
for (; i < markers.size() && markers[i] < range.end(); ++i)
|
|
|
|
out.push_back(&markers[i]);
|
|
|
|
|
|
|
|
if (range.contains(start_marker)) out.push_back(&start_marker);
|
|
|
|
if (range.contains(end_marker)) out.push_back(&end_marker);
|
2011-11-16 20:56:00 +01:00
|
|
|
|
|
|
|
keyframes_provider.GetMarkers(range, out);
|
2012-02-02 00:59:12 +01:00
|
|
|
video_position_provider.GetMarkers(range, out);
|
2011-09-28 21:44:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void AudioTimingControllerKaraoke::DoCommit() {
|
|
|
|
active_line->Text = kara->GetText();
|
|
|
|
file_changed_slot.Block();
|
2011-09-28 21:44:24 +02:00
|
|
|
commit_id = c->ass->Commit(_("karaoke timing"), AssFile::COMMIT_DIAG_TEXT, commit_id, active_line);
|
2011-09-28 21:44:07 +02:00
|
|
|
file_changed_slot.Unblock();
|
2012-11-03 23:40:54 +01:00
|
|
|
pending_changes = false;
|
2011-09-28 21:44:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void AudioTimingControllerKaraoke::Commit() {
|
2012-11-03 23:40:54 +01:00
|
|
|
if (!auto_commit && pending_changes)
|
2011-09-30 22:42:28 +02:00
|
|
|
DoCommit();
|
2011-09-28 21:44:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void AudioTimingControllerKaraoke::Revert() {
|
|
|
|
active_line = c->selectionController->GetActiveLine();
|
|
|
|
|
|
|
|
cur_syl = 0;
|
|
|
|
commit_id = -1;
|
2012-11-03 23:40:54 +01:00
|
|
|
pending_changes = false;
|
2011-09-28 21:44:07 +02:00
|
|
|
|
2012-02-02 00:58:58 +01:00
|
|
|
start_marker.Move(active_line->Start);
|
|
|
|
end_marker.Move(active_line->End);
|
2011-09-28 21:44:07 +02:00
|
|
|
|
|
|
|
markers.clear();
|
|
|
|
labels.clear();
|
|
|
|
|
|
|
|
markers.reserve(kara->size());
|
|
|
|
labels.reserve(kara->size());
|
|
|
|
|
|
|
|
for (AssKaraoke::iterator it = kara->begin(); it != kara->end(); ++it) {
|
|
|
|
if (it != kara->begin())
|
2012-02-02 00:58:58 +01:00
|
|
|
markers.push_back(KaraokeMarker(it->start_time, &separator_pen, AudioMarker::Feet_None));
|
|
|
|
labels.push_back(AudioLabel(it->text, TimeRange(it->start_time, it->start_time + it->duration)));
|
2011-09-28 21:44:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
AnnounceUpdatedPrimaryRange();
|
2011-11-18 23:58:22 +01:00
|
|
|
AnnounceUpdatedStyleRanges();
|
2011-11-16 20:56:00 +01:00
|
|
|
AnnounceMarkerMoved();
|
2011-09-28 21:44:07 +02:00
|
|
|
}
|
|
|
|
|
2012-02-22 23:00:54 +01:00
|
|
|
void AudioTimingControllerKaraoke::AddLeadIn() {
|
|
|
|
start_marker.Move(start_marker - OPT_GET("Audio/Lead/IN")->GetInt());
|
|
|
|
labels.front().range = TimeRange(start_marker, labels.front().range.end());
|
|
|
|
ApplyLead(cur_syl == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AudioTimingControllerKaraoke::AddLeadOut() {
|
|
|
|
end_marker.Move(end_marker + OPT_GET("Audio/Lead/OUT")->GetInt());
|
|
|
|
labels.back().range = TimeRange(labels.back().range.begin(), end_marker);
|
|
|
|
ApplyLead(cur_syl == markers.size());
|
|
|
|
}
|
|
|
|
|
|
|
|
void AudioTimingControllerKaraoke::ApplyLead(bool announce_primary) {
|
2012-09-25 03:56:49 +02:00
|
|
|
active_line->Start = (int)start_marker;
|
|
|
|
active_line->End = (int)end_marker;
|
2012-02-22 23:00:54 +01:00
|
|
|
kara->SetLineTimes(start_marker, end_marker);
|
2012-07-14 15:35:15 +02:00
|
|
|
if (!announce_primary)
|
|
|
|
AnnounceUpdatedStyleRanges();
|
|
|
|
AnnounceChanges(announce_primary ? cur_syl : cur_syl + 2);
|
|
|
|
}
|
2012-02-22 23:00:54 +01:00
|
|
|
|
2012-07-14 15:35:15 +02:00
|
|
|
void AudioTimingControllerKaraoke::ModifyLength(int delta, bool shift_following) {
|
|
|
|
if (cur_syl == markers.size()) return;
|
2012-02-22 23:00:54 +01:00
|
|
|
|
2012-07-14 15:35:15 +02:00
|
|
|
int cur, end, step;
|
|
|
|
if (delta < 0) {
|
|
|
|
cur = cur_syl;
|
|
|
|
end = shift_following ? markers.size() : cur_syl + 1;
|
|
|
|
step = 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
cur = shift_following ? markers.size() - 1 : cur_syl;
|
|
|
|
end = cur_syl - 1;
|
|
|
|
step = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (; cur != end; cur += step) {
|
|
|
|
MoveMarker(&markers[cur], markers[cur] + delta * 10);
|
|
|
|
}
|
|
|
|
AnnounceChanges(cur_syl);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AudioTimingControllerKaraoke::ModifyStart(int delta) {
|
|
|
|
if (cur_syl == 0) return;
|
|
|
|
MoveMarker(&markers[cur_syl - 1], markers[cur_syl - 1] + delta * 10);
|
|
|
|
AnnounceChanges(cur_syl);
|
2012-02-22 23:00:54 +01:00
|
|
|
}
|
|
|
|
|
2012-02-02 00:58:58 +01:00
|
|
|
bool AudioTimingControllerKaraoke::IsNearbyMarker(int ms, int sensitivity) const {
|
|
|
|
TimeRange range(ms - sensitivity, ms + sensitivity);
|
2011-09-28 21:44:07 +02:00
|
|
|
|
2012-11-04 04:53:03 +01:00
|
|
|
for (auto const& marker : markers)
|
|
|
|
if (range.contains(marker))
|
2011-09-28 21:44:07 +02:00
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-02-10 01:04:13 +01:00
|
|
|
std::vector<AudioMarker*> AudioTimingControllerKaraoke::OnLeftClick(int ms, bool, int sensitivity, int) {
|
2012-02-02 00:58:58 +01:00
|
|
|
TimeRange range(ms - sensitivity, ms + sensitivity);
|
2011-09-28 21:44:07 +02:00
|
|
|
|
2012-02-02 00:58:58 +01:00
|
|
|
size_t syl = distance(markers.begin(), lower_bound(markers.begin(), markers.end(), ms));
|
2011-09-28 21:44:07 +02:00
|
|
|
if (syl < markers.size() && range.contains(markers[syl]))
|
2012-02-10 01:04:13 +01:00
|
|
|
return std::vector<AudioMarker*>(1, &markers[syl]);
|
2011-09-28 21:44:07 +02:00
|
|
|
if (syl > 0 && range.contains(markers[syl - 1]))
|
2012-02-10 01:04:13 +01:00
|
|
|
return std::vector<AudioMarker*>(1, &markers[syl - 1]);
|
2011-09-28 21:44:07 +02:00
|
|
|
|
|
|
|
cur_syl = syl;
|
|
|
|
|
|
|
|
AnnounceUpdatedPrimaryRange();
|
2011-11-18 23:58:22 +01:00
|
|
|
AnnounceUpdatedStyleRanges();
|
2011-09-28 21:44:07 +02:00
|
|
|
|
2012-02-10 01:04:13 +01:00
|
|
|
return std::vector<AudioMarker*>();
|
2011-09-28 21:44:07 +02:00
|
|
|
}
|
|
|
|
|
2012-10-16 23:08:20 +02:00
|
|
|
std::vector<AudioMarker*> AudioTimingControllerKaraoke::OnRightClick(int ms, bool, int, int) {
|
|
|
|
cur_syl = distance(markers.begin(), lower_bound(markers.begin(), markers.end(), ms));
|
|
|
|
|
|
|
|
AnnounceUpdatedPrimaryRange();
|
|
|
|
AnnounceUpdatedStyleRanges();
|
|
|
|
c->audioController->PlayPrimaryRange();
|
|
|
|
|
|
|
|
return std::vector<AudioMarker*>();
|
|
|
|
}
|
|
|
|
|
2012-07-14 15:35:15 +02:00
|
|
|
int AudioTimingControllerKaraoke::MoveMarker(KaraokeMarker *marker, int new_position) {
|
2011-09-28 21:44:07 +02:00
|
|
|
// No rearranging of syllables allowed
|
|
|
|
new_position = mid(
|
|
|
|
marker == &markers.front() ? start_marker.GetPosition() : (marker - 1)->GetPosition(),
|
|
|
|
new_position,
|
|
|
|
marker == &markers.back() ? end_marker.GetPosition() : (marker + 1)->GetPosition());
|
|
|
|
|
2012-07-14 15:35:15 +02:00
|
|
|
if (new_position == marker->GetPosition())
|
|
|
|
return -1;
|
|
|
|
|
2011-09-28 21:44:07 +02:00
|
|
|
marker->Move(new_position);
|
|
|
|
|
|
|
|
size_t syl = marker - &markers.front() + 1;
|
2012-10-10 05:39:43 +02:00
|
|
|
kara->SetStartTime(syl, (new_position + 5) / 10 * 10);
|
2011-09-28 21:44:07 +02:00
|
|
|
|
2012-07-14 15:35:15 +02:00
|
|
|
labels[syl - 1].range = TimeRange(labels[syl - 1].range.begin(), new_position);
|
|
|
|
labels[syl].range = TimeRange(new_position, labels[syl].range.end());
|
|
|
|
|
|
|
|
return syl;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AudioTimingControllerKaraoke::AnnounceChanges(int syl) {
|
|
|
|
if (syl < 0) return;
|
|
|
|
|
2012-01-20 02:49:41 +01:00
|
|
|
if (syl == cur_syl || syl == cur_syl + 1) {
|
2011-09-28 21:44:07 +02:00
|
|
|
AnnounceUpdatedPrimaryRange();
|
2011-11-18 23:58:22 +01:00
|
|
|
AnnounceUpdatedStyleRanges();
|
|
|
|
}
|
2011-11-16 20:56:00 +01:00
|
|
|
AnnounceMarkerMoved();
|
|
|
|
AnnounceLabelChanged();
|
2011-09-28 21:44:07 +02:00
|
|
|
|
|
|
|
if (auto_commit)
|
|
|
|
DoCommit();
|
2012-11-03 23:40:54 +01:00
|
|
|
else {
|
|
|
|
pending_changes = true;
|
2011-09-28 21:44:07 +02:00
|
|
|
commit_id = -1;
|
2012-11-03 23:40:54 +01:00
|
|
|
}
|
2011-09-28 21:44:07 +02:00
|
|
|
}
|
|
|
|
|
2012-07-14 15:35:15 +02:00
|
|
|
void AudioTimingControllerKaraoke::OnMarkerDrag(std::vector<AudioMarker*> const& m, int new_position, int) {
|
|
|
|
assert(m.size() == 1);
|
|
|
|
AnnounceChanges(MoveMarker(static_cast<KaraokeMarker*>(m[0]), new_position));
|
|
|
|
}
|
|
|
|
|
2012-02-02 00:58:58 +01:00
|
|
|
void AudioTimingControllerKaraoke::GetLabels(TimeRange const& range, std::vector<AudioLabel> &out) const {
|
2012-11-04 04:53:03 +01:00
|
|
|
for (auto const& label : labels) {
|
|
|
|
if (range.overlaps(label.range))
|
|
|
|
out.push_back(label);
|
2011-09-28 21:44:07 +02:00
|
|
|
}
|
|
|
|
}
|