Example #1
0
/// @brief Actually process subtitles
///
void DialogTimingProcessor::Process() {
    SortDialogues();
    int rows = Sorted.size();

    // Options
    long inVal = 0;
    long outVal = 0;
    leadIn->GetValue().ToLong(&inVal);
    leadOut->GetValue().ToLong(&outVal);
    bool addIn = hasLeadIn->IsChecked() && inVal;
    bool addOut = hasLeadOut->IsChecked() && outVal;

    // Add lead-in/out
    if (addIn || addOut) {
        for (int i=0; i<rows; i++) {
            AssDialogue *cur = Sorted[i];

            // Compare to every previous line (yay for O(n^2)!) to see if it's OK to add lead-in
            if (inVal) {
                int startLead = cur->Start.GetMS() - inVal;
                for (int j=0; j<i; j++) {
                    AssDialogue *comp = Sorted[j];

                    // Check if they don't already collide (ignore it in that case)
                    if (cur->CollidesWith(comp)) continue;

                    // Get comparison times
                    startLead = std::max(startLead, comp->End.GetMS());
                }
                cur->Start.SetMS(startLead);
            }

            // Compare to every line to see how far can lead-out be extended
            if (outVal) {
                int endLead = cur->End.GetMS() + outVal;
                for (int j=i+1; j<rows; j++) {
                    AssDialogue *comp = Sorted[j];

                    // Check if they don't already collide (ignore it in that case)
                    if (cur->CollidesWith(comp)) continue;

                    // Get comparison times
                    endLead = std::min(endLead, comp->Start.GetMS());
                }
                cur->End.SetMS(endLead);
            }
        }
    }

    // Make adjacent
    if (adjsEnable->IsChecked()) {
        AssDialogue *prev = Sorted.front();

        long adjsThres = 0;
        adjacentThres->GetValue().ToLong(&adjsThres);

        float bias = adjacentBias->GetValue() / 100.0;

        for (int i=1; i < rows; i++) {
            AssDialogue *cur = Sorted[i];

            // Check if they don't collide
            if (cur->CollidesWith(prev)) continue;

            // Compare distance
            int curStart = cur->Start.GetMS();
            int prevEnd = prev->End.GetMS();
            int dist = curStart-prevEnd;
            if (dist > 0 && dist < adjsThres) {
                int setPos = prevEnd+int(dist*bias);
                cur->Start.SetMS(setPos);
                prev->End.SetMS(setPos);
            }

            prev = cur;
        }
    }

    // Keyframe snapping
    if (keysEnable->IsChecked()) {
        KeyFrames = c->videoController->GetKeyFrames();
        KeyFrames.push_back(c->videoController->GetLength() - 1);

        long beforeStart = 0;
        long afterStart = 0;
        long beforeEnd = 0;
        long afterEnd = 0;
        keysStartBefore->GetValue().ToLong(&beforeStart);
        keysStartAfter->GetValue().ToLong(&afterStart);
        keysEndBefore->GetValue().ToLong(&beforeEnd);
        keysEndAfter->GetValue().ToLong(&afterEnd);

        for (int i=0; i<rows; i++) {
            AssDialogue *cur = Sorted[i];

            // Get start/end frames
            int startF = c->videoController->FrameAtTime(cur->Start.GetMS(),agi::vfr::START);
            int endF = c->videoController->FrameAtTime(cur->End.GetMS(),agi::vfr::END);

            // Get closest for start
            int closest = GetClosestKeyFrame(startF);
            if ((closest > startF && closest-startF <= beforeStart) || (closest < startF && startF-closest <= afterStart)) {
                cur->Start.SetMS(c->videoController->TimeAtFrame(closest,agi::vfr::START));
            }

            // Get closest for end
            closest = GetClosestKeyFrame(endF)-1;
            if ((closest > endF && closest-endF <= beforeEnd) || (closest < endF && endF-closest <= afterEnd)) {
                cur->End.SetMS(c->videoController->TimeAtFrame(closest,agi::vfr::END));
            }
        }
    }

    // Update grid
    c->ass->Commit(_("timing processor"), AssFile::COMMIT_TIMES);
}
//////////////////////////////
// Actually process subtitles
void DialogTimingProcessor::Process() {
	// Sort rows
	SortDialogues();
	int rows = Sorted.size();

	// Options
	long inVal = 0;
	long outVal = 0;
	leadIn->GetValue().ToLong(&inVal);
	leadOut->GetValue().ToLong(&outVal);
	bool addIn = hasLeadIn->IsChecked() && inVal;
	bool addOut = hasLeadOut->IsChecked() && outVal;

	// Add lead-in/out
	if (addIn || addOut) {
		// Variables
		AssDialogue *cur;
		AssDialogue *comp;
		int start,end;
		int startLead,endLead;
		int compStart,compEnd;

		// For each row
		for (int i=0;i<rows;i++) {
			// Get line and check if it's OK
			cur = GetSortedDialogue(i);

			// Set variables
			start = cur->Start.GetMS();
			end = cur->End.GetMS();
			if (addIn) startLead = start - inVal;
			else startLead = start;
			if (addOut) endLead = end + outVal;
			else endLead = end;

			// Compare to every previous line (yay for O(n^2)!) to see if it's OK to add lead-in
			if (addIn) {
				for (int j=0;j<i;j++) {
					comp = GetSortedDialogue(j);

					// Check if they don't already collide (ignore it in that case)
					if (cur->CollidesWith(comp)) continue;

					// Get comparison times
					compEnd = comp->End.GetMS();

					// Limit lead-in if needed
					if (compEnd > startLead) startLead = compEnd;
				}
			}

			// Compare to every line to see how far can lead-out be extended
			if (addOut) {
				for (int j=i+1;j<rows;j++) {
					comp = GetSortedDialogue(j);

					// Check if they don't already collide (ignore it in that case)
					if (cur->CollidesWith(comp)) continue;

					// Get comparison times
					compStart = comp->Start.GetMS();

					// Limit lead-in if needed
					if (compStart < endLead) endLead = compStart;
				}
			}

			// Set times
			cur->Start.SetMS(startLead);
			cur->End.SetMS(endLead);
			cur->UpdateData();
		}
	}

	// Make adjascent
	if (adjsEnable->IsChecked()) {
		// Variables
		AssDialogue *cur;
		AssDialogue *prev = NULL;
		int curStart,prevEnd;
		long adjsThres = 0;
		int dist;

		// Get threshold
		adjascentThres->GetValue().ToLong(&adjsThres);

		// Get bias
		float bias = adjascentBias->GetValue() / 100.0;

		// For each row
		for (int i=0;i<rows;i++) {
			// Get line and check if it's OK
			cur = GetSortedDialogue(i);

			// Check if previous is OK
			if (!prev) {
				prev = cur;
				continue;
			}

			// Check if they don't collide
			if (cur->CollidesWith(prev)) continue;

			// Compare distance
			curStart = cur->Start.GetMS();
			prevEnd = prev->End.GetMS();
			dist = curStart-prevEnd;
			if (dist > 0 && dist < adjsThres) {
				int setPos = prevEnd+int(dist*bias);
				cur->Start.SetMS(setPos);
				cur->UpdateData();
				prev->End.SetMS(setPos);
				prev->UpdateData();
			}

			// Set previous
			prev = cur;
		}
	}

	// Keyframe snapping
	if (keysEnable->IsChecked()) {
		// Get keyframes
		KeyFrames = grid->video->KeyFrames;
		KeyFrames.Add(grid->video->length-1);

		// Variables
		int startF,endF;
		int closest;
		bool changed;
		AssDialogue *cur;

		// Get variables
		long beforeStart = 0;
		long afterStart = 0;
		long beforeEnd = 0;
		long afterEnd = 0;
		keysStartBefore->GetValue().ToLong(&beforeStart);
		keysStartAfter->GetValue().ToLong(&afterStart);
		keysEndBefore->GetValue().ToLong(&beforeEnd);
		keysEndAfter->GetValue().ToLong(&afterEnd);
		
		// For each row
		for (int i=0;i<rows;i++) {
			// Get line and check if it's OK
			cur = GetSortedDialogue(i);

			// Get start/end frames
			startF = VFR_Output.GetFrameAtTime(cur->Start.GetMS(),true);
			endF = VFR_Output.GetFrameAtTime(cur->End.GetMS(),false);
			changed = false;

			// Get closest for start
			closest = GetClosestKeyFrame(startF);
			if ((closest > startF && closest-startF <= beforeStart) || (closest < startF && startF-closest <= afterStart)) {
				cur->Start.SetMS(VFR_Output.GetTimeAtFrame(closest,true));
				changed = true;
			}

			// Get closest for end
			closest = GetClosestKeyFrame(endF)-1;
			if ((closest > endF && closest-endF <= beforeEnd) || (closest < endF && endF-closest <= afterEnd)) {
				cur->End.SetMS(VFR_Output.GetTimeAtFrame(closest,false));
				changed = true;
			}

			// Apply changes
			if (changed) {
				cur->UpdateData();
			}
		}
	}

	// Update grid
	grid->ass->FlagAsModified();
	grid->CommitChanges();
}