/// <summary> /// Validate GUI. Inform user if they entered invalid data. /// </summary> private bool validateForm() { bool status = false; invalidCount = 0; ValidateChildren(); if (invalidCount == 0) { status = true; } else if (invalidCount == 1) { UtilsMsg.showErrMsg("Please correct the error on this form." + "\r\n\r\nHover the mouse over the red error bubble" + "\r\nto determine the nature of the error."); } else { UtilsMsg.showErrMsg($"Please correct the {invalidCount} errors on this form." + "\r\n\r\nHover the mouse over the red error bubbles" + "\r\nto determine the nature of the errors."); } return(status); }
/// <summary> /// Gets called when all subtitle processing is finished (or cancelled). /// </summary> private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (dialogProgress != null) { dialogProgress.Hide(); dialogProgress = null; } if (e.Error != null) { UtilsMsg.showErrMsg(e.Error.Message); return; } if (e.Cancelled) { MessageBox.Show("Action cancelled.", UtilsAssembly.Title, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } TimeSpan workerTotalTime = DateTime.Now - workerStartTime; WorkerVars workerVars = e.Result as WorkerVars; string srsFormat = getSrsFormatList(); string endMessage = $"Processing completed in {workerTotalTime.TotalMinutes:0.00} minutes.\n\n{srsFormat}"; UtilsMsg.showInfoMsg(endMessage); }
/// <summary> /// Called when the audio extraction thread completes. /// </summary> private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (dialogProgress != null) { dialogProgress.Hide(); dialogProgress = null; } if (e.Error != null) { UtilsMsg.showErrMsg(e.Error.Message); return; } if (e.Cancelled) { MessageBox.Show("Action cancelled.", UtilsAssembly.Title, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } TimeSpan workerTotalTime = DateTime.Now - this.workerStartTime; WorkerVars workerVars = e.Result as WorkerVars; string endMessage = String.Format("Audio extraction completed in {0:0.00} minutes.", workerTotalTime.TotalMinutes); UtilsMsg.showInfoMsg(endMessage); }
private void buttonGo_Click(object sender, EventArgs e) { int activeLongLineCount = this.getNumberOfLongActiveLines(previewWorkerVars.CombinedAll); if (activeLongLineCount > 0) { bool cont = UtilsMsg.showConfirm(String.Format("There are {0} active lines that have a long duration (> {1} seconds).\r\n\r\n" + "Do you wish to continue?\r\n\r\n" + "(These long lines are colored red. See \"Preferences > Misc > Long Clip Warning\" to configure threshold.)", activeLongLineCount, ConstantSettings.LongClipWarningSeconds)); if (!cont) { return; } } SubsProcessor subsProcessor = new SubsProcessor(); if ((previewWorkerVars != null) && (previewWorkerVars.CombinedAll != null)) { subsProcessor.start(previewWorkerVars.CombinedAll); } }
private void DialogPreview_FormClosed(object sender, FormClosedEventArgs e) { if (previewWorkerVars != null) { if (Directory.Exists(previewWorkerVars.MediaDir)) { try { Directory.Delete(previewWorkerVars.MediaDir, true); } catch { UtilsMsg.showErrMsg("Unable to delete the temporary directory at:\n" + previewWorkerVars.MediaDir); } } } // Kill the video player in case this dialog is killed by the main form if (videoPlayerProcess != null) { if (!videoPlayerProcess.HasExited) { videoPlayerProcess.Kill(); } } }
/// <summary> /// Gets called when all preview's subtitle processing is finished (or cancelled). /// </summary> private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (dialogProgress != null) { dialogProgress.Hide(); dialogProgress = null; } if (e.Error != null) { UtilsMsg.showErrMsg(e.Error.Message); return; } if (e.Cancelled) { return; } WorkerVars workerVars = e.Result as WorkerVars; previewWorkerVars = workerVars; updateStats(); populateLinesListView(this.comboBoxEpisode.SelectedIndex); Logger.Instance.info("Preview: COMPLETED"); }
/// <summary> /// Write a list of settings to the settings file. /// </summary> public static void writeString(List <SettingsPair> settingsList) { try { // Read settings file into memory StreamReader reader = new StreamReader(ConstantSettings.SettingsFilename, Encoding.UTF8); string contents = reader.ReadToEnd(); reader.Close(); // Replace each setting in list foreach (SettingsPair pair in settingsList) { string regex = "^" + pair.Key + @"\s*?=.*$"; string replacement = pair.Key + " = " + pair.Value; contents = Regex.Replace(contents, regex, replacement, RegexOptions.Multiline); } // Write settings back out to file TextWriter writer = new StreamWriter(ConstantSettings.SettingsFilename, false, Encoding.UTF8); writer.Write(contents); writer.Close(); } catch { UtilsMsg.showErrMsg("Unable to find the preferences file: '" + ConstantSettings.SettingsFilename + "'\r\nPreferences will not be saved."); } }
/// <summary> /// Open a file meant to populate an exclude or include only field. /// </summary> private string getIncludeExludeTextFromFile() { string outStr = ""; OpenFileDialog openDialog = new OpenFileDialog(); StreamReader fileStream; openDialog.Filter = "Text files (*.txt)|*.txt"; openDialog.FilterIndex = 1; openDialog.RestoreDirectory = true; openDialog.Multiselect = false; if (openDialog.ShowDialog() == DialogResult.OK) { try { if ((fileStream = new StreamReader(openDialog.OpenFile())) != null) { string fileText = fileStream.ReadToEnd().Trim(); string[] words = fileText.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); outStr = UtilsCommon.makeSemiString(words); fileStream.Close(); } } catch { UtilsMsg.showErrMsg("Could not open file."); return(null); } } return(outStr); }
/// <summary> /// Experimental video preview on the selected line. /// </summary> private void buttonPreviewVideo_Click(object sender, EventArgs e) { string videoConfigPlayer = ""; if (previewWorkerVars == null || currentInfoComb == null || Settings.Instance.VideoClips.Files.Length == 0) { return; } videoConfigPlayer = ConstantSettings.VideoPlayer; // Check if the player exists if (!File.Exists(videoConfigPlayer)) { UtilsMsg.showErrMsg( $"The video player \"{ConstantSettings.VideoPlayer}\" \nprovided in {ConstantSettings.SettingsFilename} does not exist!"); return; } // Kill the player before running it again. // For some reason the players that I tested (MPC-HC, ZoomPlayer, VLC) don't // read the start time arg correctly unless they are killed first. if (videoPlayerProcess != null) { if (!videoPlayerProcess.HasExited) { videoPlayerProcess.Kill(); } } DateTime startTime = currentInfoComb.Subs1.StartTime; DateTime endTime = currentInfoComb.Subs1.EndTime; // Apply pad (if requested) if (Settings.Instance.VideoClips.PadEnabled) { startTime = UtilsSubs.applyTimePad(startTime, -Settings.Instance.VideoClips.PadStart); endTime = UtilsSubs.applyTimePad(endTime, Settings.Instance.VideoClips.PadEnd); } UtilsName name = new UtilsName(Settings.Instance.DeckName, Settings.Instance.VideoClips.Files.Length, 0, endTime, Settings.Instance.VideoClips.Size.Width, Settings.Instance.VideoClips.Size.Height); string videoConfigArgs = name.createName(ConstantSettings.VideoPlayerArgs, comboBoxEpisode.SelectedIndex + Settings.Instance.EpisodeStartNumber - 1, 0, startTime, endTime, "", ""); string videoFileName = Settings.Instance.VideoClips.Files[comboBoxEpisode.SelectedIndex]; string procArgs = $"{videoConfigArgs} \"{videoFileName}\""; // Play the video videoPlayerProcess = new Process(); videoPlayerProcess.StartInfo.FileName = videoConfigPlayer; videoPlayerProcess.StartInfo.Arguments = procArgs; videoPlayerProcess.StartInfo.UseShellExecute = false; videoPlayerProcess.StartInfo.CreateNoWindow = true; videoPlayerProcess.Start(); }
/// <summary> /// Update the information related to Subs1 or Subs2. /// </summary> private void updateSubs(int subsNum) { TextBox textbox; string file; // Get items that depend on whether it's subs1 or subs2 if (subsNum == 1) { textbox = this.textBoxSubs1File; file = this.textBoxSubs1File.Text.Trim(); } else { textbox = this.textBoxSubs2File; file = this.textBoxSubs2File.Text.Trim(); } // If input file is an MKV, show the MKV track select dialog if (Path.GetExtension(file) == ".mkv") { List <MkvTrack> allSubTrackList = UtilsMkv.getSubtitleTrackList(file); List <MkvTrack> subTrackList = new List <MkvTrack>(); // Remove VOBSUB tracks foreach (MkvTrack subTrack in allSubTrackList) { if (subTrack.Extension != "sub") { subTrackList.Add(subTrack); } } if (subTrackList.Count == 0) { UtilsMsg.showInfoMsg("This .mkv file does not contain any subtitle tracks."); textbox.Text = ""; } else { DialogSelectMkvTrack mkvDlg = new DialogSelectMkvTrack(file, subsNum, subTrackList); DialogResult result = mkvDlg.ShowDialog(); if (result == DialogResult.OK) { textbox.Text = mkvDlg.ExtractedFile; } else { textbox.Text = ""; } } return; // Since textbox.Text was changed, this routine will be called again } }
/// <summary> /// Reprocess the subtitles and discard active/inactive and text changes made by the user. /// </summary> private void buttonRegenerate_Click(object sender, EventArgs e) { string oldSubs1 = "-----"; string oldSubs2 = "-----"; if (changesHaveBeenMade) { bool confirmed = UtilsMsg.showConfirm("Regenerate the preview and discard the changes that you have made?"); if (!confirmed) { return; } } changesHaveBeenMade = false; // Save the currently selected item if (currentInfoComb != null) { InfoCombined selectedComb = currentInfoComb; oldSubs1 = selectedComb.Subs1.Text; oldSubs2 = selectedComb.Subs2.Text; } generatePreview(); int indexOfItemToSelect = 0; // Try to select the saved item for (int i = 0; i < listViewLines.Items.Count; i++) { InfoCombined curComb = (InfoCombined)listViewLines.Items[i].Tag; if (curComb.Subs1.Text == oldSubs1 && curComb.Subs2.Text == oldSubs2) { indexOfItemToSelect = i; break; } } if (listViewLines.Items.Count > 0) { listViewLines.Focus(); listViewLines.Items[indexOfItemToSelect].Selected = true; listViewLines.EnsureVisible(indexOfItemToSelect); } }
/// <summary> /// Start the processing in a seperate thread. /// If combinedAll is not null, use it rather then generating a new combinedAll. /// </summary> public void start(List <List <InfoCombined> > combinedAll) { // Create directory stucture try { createOutputDirStructure(); } catch { UtilsMsg.showErrMsg("Cannot write to output directory. \nTry checking the directory's permissions."); return; } Logger.Instance.info("SubsProcessor.start"); Logger.Instance.writeSettingsToLog(); // Start the worker thread try { WorkerVars workerVars = new WorkerVars(combinedAll, getMediaDir(Settings.Instance.OutputDir, Settings.Instance.DeckName), WorkerVars.SubsProcessingType.Normal); // Create a background thread BackgroundWorker bw = new BackgroundWorker(); bw.DoWork += new DoWorkEventHandler(bw_DoWork); bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted); // Create a progress dialog on the UI thread dialogProgress = new DialogProgress(); currentStep = 0; dialogProgress.StepsTotal = determineNumSteps(combinedAll); workerStartTime = DateTime.Now; bw.RunWorkerAsync(workerVars); // Lock up the UI with this modal progress form dialogProgress.ShowDialog(); dialogProgress = null; } catch (Exception e1) { UtilsMsg.showErrMsg("Something went wrong before processing could start.\n" + e1); return; } }
private void backgroundWorkerMain_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (e.Cancelled) { // Don't care } else if (e.Error != null) { UtilsMsg.showErrMsg("Something went wrong: " + e.Error.Message); } else { UtilsMsg.showInfoMsg("Extraction complete."); } resetGuiToStartingState(); }
private void updateSettings() { try { Settings.Instance.Subs[0].FilePattern = textBoxSubs1File.Text.Trim(); Settings.Instance.Subs[0].TimingsEnabled = radioButtonTimingSubs1.Checked; Settings.Instance.Subs[0].TimeShift = (int)numericUpDownTimeShiftSubs1.Value; Settings.Instance.Subs[0].Files = UtilsSubs.getSubsFiles(Settings.Instance.Subs[0].FilePattern).ToArray(); Settings.Instance.Subs[0].Encoding = InfoEncoding.longToShort(this.comboBoxEncodingSubs1.Text); Settings.Instance.Subs[0].RemoveNoCounterpart = this.checkBoxRemoveLinesWithoutCounterpartSubs1.Checked; Settings.Instance.Subs[0].RemoveStyledLines = this.checkBoxRemoveStyledLinesSubs1.Checked; Settings.Instance.Subs[1].FilePattern = textBoxSubs2File.Text.Trim(); Settings.Instance.Subs[1].TimingsEnabled = radioButtonTimingSubs2.Checked; Settings.Instance.Subs[1].TimeShift = (int)numericUpDownTimeShiftSubs2.Value; Settings.Instance.Subs[1].Files = UtilsSubs.getSubsFiles(Settings.Instance.Subs[1].FilePattern).ToArray(); Settings.Instance.Subs[1].Encoding = InfoEncoding.longToShort(this.comboBoxEncodingSubs2.Text); Settings.Instance.Subs[1].RemoveNoCounterpart = this.checkBoxRemoveLinesWithoutCounterpartSubs2.Checked; Settings.Instance.Subs[1].RemoveStyledLines = this.checkBoxRemoveStyledLinesSubs2.Checked; Settings.Instance.OutputDir = textBoxOutputDir.Text.Trim(); Settings.Instance.TimeShiftEnabled = groupBoxTimeShift.Checked; Settings.Instance.DeckName = textBoxName.Text.Trim(); Settings.Instance.EpisodeStartNumber = (int)numericUpDownEpisodeStartNumber.Value; duelPattern = (int)this.numericUpDownPattern.Value; isSubs1First = (this.comboBoxPriority.SelectedIndex == 0); quickReference = this.checkBoxQuickReference.Checked; } catch (Exception e1) { UtilsMsg.showErrMsg("Something went wrong while gathering interface data:\n" + e1); return; } }
/// <summary> /// Extract the audio from the media. /// </summary> private void buttonExtract_Click(object sender, EventArgs e) { errorProvider1.Clear(); if (validateForm()) { updateSettings(); Logger.Instance.info("Extract Audio From Media: GO!"); Logger.Instance.writeSettingsToLog(); // Start the worker thread try { WorkerVars workerVars = new WorkerVars(null, Settings.Instance.OutputDir, WorkerVars.SubsProcessingType.Normal); // Create a background thread BackgroundWorker bw = new BackgroundWorker(); bw.DoWork += new DoWorkEventHandler(splitAudio); bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted); // Create a progress dialog on the UI thread dialogProgress = new DialogProgress(); this.workerStartTime = DateTime.Now; bw.RunWorkerAsync(workerVars); // Lock up the UI with this modal progress form dialogProgress.ShowDialog(); dialogProgress = null; } catch (Exception e1) { UtilsMsg.showErrMsg("Something went wrong before processing could start.\n" + e1); return; } } }
/// <summary> /// Called when the Dueling Subtitles creation thread completes. /// </summary> private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (dialogProgress != null) { dialogProgress.Hide(); dialogProgress = null; } if (e.Error != null) { UtilsMsg.showErrMsg(e.Error.Message); return; } if (e.Cancelled) { MessageBox.Show("Action cancelled.", UtilsAssembly.Title, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } WorkerVars workerVars = e.Result as WorkerVars; UtilsMsg.showInfoMsg("Dueling subtitles have been created successfully."); }
/// <summary> /// Perform the work in the Dueling Subtitles creation thread. /// </summary> private void bw_DoWork(object sender, DoWorkEventArgs e) { WorkerVars workerVars = e.Argument as WorkerVars; List <List <InfoCombined> > combinedAll = new List <List <InfoCombined> >(); WorkerSubs subsWorker = new WorkerSubs(); // Parse and combine the subtitles try { combinedAll = subsWorker.combineAllSubs(workerVars, dialogProgress); if (combinedAll != null) { workerVars.CombinedAll = combinedAll; } else { e.Cancel = true; return; } } catch (Exception e1) { UtilsMsg.showErrMsg("Something went wrong before processing could start.\n" + e1); e.Cancel = true; return; } // Create the .ass file try { if (!createDuelingSubtitles(workerVars, dialogProgress)) { e.Cancel = true; return; } } catch (Exception e1) { UtilsMsg.showErrMsg("Something went wrong when generating the Dueling Subtitles.\n" + e1); e.Cancel = true; return; } // Create the quick reference file if (quickReference) { try { if (!createQuickReference(workerVars, dialogProgress)) { e.Cancel = true; return; } } catch (Exception e1) { UtilsMsg.showErrMsg("Something went wrong when generating the quick reference file.\n" + e1); e.Cancel = true; return; } } }
/// <summary> /// Does the work of the preview thread. Performs the processing on subtitles. /// </summary> private void bw_DoWork(object sender, DoWorkEventArgs e) { WorkerVars workerVars = e.Argument as WorkerVars; List <List <InfoCombined> > combinedAll = new List <List <InfoCombined> >(); WorkerSubs subsWorker = new WorkerSubs(); int totalLines = 0; // Parse and combine the subtitles try { combinedAll = subsWorker.combineAllSubs(workerVars, dialogProgress); if (combinedAll != null) { workerVars.CombinedAll = combinedAll; } else { e.Cancel = true; return; } } catch (Exception e1) { UtilsMsg.showErrMsg("Something went wrong before processing could start.\n" + e1); e.Cancel = true; return; } foreach (List <InfoCombined> combArray in workerVars.CombinedAll) { totalLines += combArray.Count; } if (totalLines == 0) { UtilsMsg.showErrMsg("No lines of dialog could be parsed from the subtitle files.\nPlease check that they are valid."); e.Cancel = true; return; } // Remove lines try { combinedAll = subsWorker.inactivateLines(workerVars, dialogProgress); if (combinedAll != null) { workerVars.CombinedAll = combinedAll; } else { e.Cancel = true; return; } } catch (Exception e1) { UtilsMsg.showErrMsg("Something went wrong while removing lines.\n" + e1); e.Cancel = true; return; } totalLines = 0; foreach (List <InfoCombined> combArray in workerVars.CombinedAll) { totalLines += combArray.Count; } if (totalLines == 0) { UtilsMsg.showErrMsg("No lines will be processed. Please check your settings to make\nsure that you are not mistakenly pruning too many lines."); e.Cancel = true; return; } e.Result = workerVars; }
/// <summary> /// Generate the preview in seperate thread. /// </summary> private void generatePreview() { // Fire event to tell MainForm to update the settings if (GeneretePreview != null) { GeneretePreview(this, EventArgs.Empty); } populateEpisodeComboBox(); string tempPreviewDir = Path.GetTempPath() + ConstantSettings.TempPreviewDirName; if (Directory.Exists(tempPreviewDir)) { try { Directory.Delete(tempPreviewDir, true); } catch { //UtilsMsg.showErrMsg("Unable to delete the temporary directory at:\n" + tempPreviewDir); } } // Create the temporary directory try { Directory.CreateDirectory(tempPreviewDir); } catch { UtilsMsg.showErrMsg("Cannot write to " + tempPreviewDir + "\nTry checking the directory's permissions."); return; } Logger.Instance.info("Preview: GO!"); Logger.Instance.writeSettingsToLog(); // Start the worker thread try { WorkerVars workerVars = new WorkerVars(null, tempPreviewDir, WorkerVars.SubsProcessingType.Preview); // Create a background thread BackgroundWorker bw = new BackgroundWorker(); bw.DoWork += new DoWorkEventHandler(bw_DoWork); bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted); // Create a progress dialog on the UI thread dialogProgress = new DialogProgress(); bw.RunWorkerAsync(workerVars); // Lock up the UI with this modal progress form dialogProgress.ShowDialog(); dialogProgress = null; } catch (Exception e1) { UtilsMsg.showErrMsg("Something went wrong before preview could be generated.\n" + e1); return; } }
/// <summary> /// Performs the work of the audio extraction thread. /// </summary> private void splitAudio(object sender, DoWorkEventArgs e) { WorkerVars workerVars = e.Argument as WorkerVars; List <List <InfoCombined> > combinedAll = new List <List <InfoCombined> >(); WorkerSubs subsWorker = new WorkerSubs(); if (groupBoxCheckLyrics.Checked) { // Parse and combine the subtitles try { combinedAll = subsWorker.combineAllSubs(workerVars, dialogProgress); if (combinedAll != null) { workerVars.CombinedAll = combinedAll; } else { e.Cancel = true; return; } } catch (Exception e1) { UtilsMsg.showErrMsg("Something went wrong before processing could start.\n" + e1); e.Cancel = true; return; } } DateTime mediaStartime = new DateTime(); DateTime mediaEndtime = new DateTime(); DateTime mediaDuration = new DateTime(); int episode = 0; DialogProgress.updateProgressInvoke(dialogProgress, 0, "Starting..."); foreach (string file in mediaFiles) { episode++; try { mediaEndtime = UtilsVideo.getVideoLength(file); } catch (Exception e1) { UtilsMsg.showErrMsg("Something went wrong while determining duration of the media:\n" + e1); return; } if (useSpan) { mediaStartime = spanStart; // If the span end time if not greater than the actual duration of the media if (spanEnd < mediaEndtime) { mediaEndtime = spanEnd; } } UtilsName name = new UtilsName( deckName, mediaFiles.Length, // Total number of episodes 1, // Total number of lines (Note: not filled out here) mediaEndtime, // Last time 0, 0 // Width and height (Note: not filled out anywhere) ); mediaDuration = UtilsSubs.getDurationTime(mediaStartime, mediaEndtime); string progressText = String.Format("Processing audio from media file {0} of {1}", episode, mediaFiles.Length); int progress = Convert.ToInt32((episode - 1) * (100.0 / mediaFiles.Length)); DialogProgress.updateProgressInvoke(dialogProgress, progress, progressText); // Enable detail mode in progress dialog DialogProgress.enableDetailInvoke(dialogProgress, true); // Set the duration of the clip in the progress dialog (for detail mode) DialogProgress.setDuration(dialogProgress, mediaDuration); string tempMp3Filename = Path.GetTempPath() + ConstantSettings.TempAudioFilename; UtilsAudio.ripAudioFromVideo(mediaFiles[episode - 1], audioStream.Num, mediaStartime, mediaEndtime, bitrate, tempMp3Filename, dialogProgress); DialogProgress.enableDetailInvoke(dialogProgress, false); if (dialogProgress.Cancel) { e.Cancel = true; File.Delete(tempMp3Filename); return; } int numClips = 1; if (!isSingleFile) { numClips = (int)Math.Ceiling((mediaDuration.TimeOfDay.TotalMilliseconds / (clipLength.TimeOfDay.TotalSeconds * 1000.0))); } for (int clipIdx = 0; clipIdx < numClips; clipIdx++) { progressText = String.Format("Splitting segment {0} of {1} from media file {2} of {3}", clipIdx + 1, numClips, episode, mediaFiles.Length); progress = Convert.ToInt32((episode - 1) * (100.0 / mediaFiles.Length)); DialogProgress.updateProgressInvoke(dialogProgress, progress, progressText); if (dialogProgress.Cancel) { e.Cancel = true; File.Delete(tempMp3Filename); return; } // The start and end times used for processing DateTime startTime = new DateTime(); DateTime endTime = new DateTime(); if (isSingleFile) { endTime = mediaDuration; } else { startTime = startTime.AddSeconds((double)(clipLength.TimeOfDay.TotalSeconds * clipIdx)); endTime = endTime.AddSeconds((double)(clipLength.TimeOfDay.TotalSeconds * (clipIdx + 1))); if (endTime.TimeOfDay.TotalMilliseconds >= mediaDuration.TimeOfDay.TotalMilliseconds) { endTime = mediaDuration; } } // The start and end times that will be displayed DateTime startTimeName = startTime.AddMilliseconds(mediaStartime.TimeOfDay.TotalMilliseconds); DateTime endTimeName = endTime.AddMilliseconds(mediaStartime.TimeOfDay.TotalMilliseconds); // Fill in the total number of lines with the total number of clips name.TotalNumLines = numClips; string nameStr = name.createName(ConstantSettings.ExtractMediaAudioFilenameFormat, episode + episodeStartNumber - 1, clipIdx + 1, startTimeName, endTimeName, "", ""); string outName = String.Format("{0}{1}{2}", outputDir, // {0} Path.DirectorySeparatorChar, // {1} nameStr); // {2} UtilsAudio.cutAudio(tempMp3Filename, startTime, endTime, outName); nameStr = name.createName(ConstantSettings.AudioId3Artist, episode + episodeStartNumber - 1, clipIdx + 1, startTimeName, endTimeName, "", ""); string tagArtist = String.Format("{0}", nameStr); // {0} nameStr = name.createName(ConstantSettings.AudioId3Album, episode + episodeStartNumber - 1, clipIdx + 1, startTimeName, endTimeName, "", ""); string tagAlbum = String.Format("{0}", nameStr); // {0} nameStr = name.createName(ConstantSettings.AudioId3Title, episode + episodeStartNumber - 1, clipIdx + 1, startTimeName, endTimeName, "", ""); string tagTitle = String.Format("{0}", nameStr); // {0} nameStr = name.createName(ConstantSettings.AudioId3Genre, episode + episodeStartNumber - 1, clipIdx + 1, startTimeName, endTimeName, "", ""); string tagGenre = String.Format("{0}", nameStr); // {0} string tagLyrics = ""; if (groupBoxCheckLyrics.Checked) { int totalLyricsLines = 0; int curLyricsNum = 1; // Precount the number of lyrics lines foreach (InfoCombined comb in combinedAll[episode - 1]) { if (comb.Subs1.StartTime.TimeOfDay.TotalMilliseconds >= startTimeName.TimeOfDay.TotalMilliseconds && comb.Subs1.StartTime.TimeOfDay.TotalMilliseconds <= endTimeName.TimeOfDay.TotalMilliseconds) { totalLyricsLines++; } } // Fill in the total number of lyrics lines name.TotalNumLines = curLyricsNum; // Foreach comb in the current episode, if the comb lies within the // current clip, add it to the lryics tag foreach (InfoCombined comb in combinedAll[episode - 1]) { if (comb.Subs1.StartTime.TimeOfDay.TotalMilliseconds >= startTimeName.TimeOfDay.TotalMilliseconds && comb.Subs1.StartTime.TimeOfDay.TotalMilliseconds <= endTimeName.TimeOfDay.TotalMilliseconds) { tagLyrics += formatLyricsPair(comb, name, startTimeName, episode + episodeStartNumber - 1, curLyricsNum) + "\r\n"; curLyricsNum++; } } } UtilsAudio.tagAudio(outName, tagArtist, tagAlbum, tagTitle, tagGenre, tagLyrics, clipIdx + 1, numClips); } } return; }
/// <summary> /// Generate Audio clips for all episodes. /// </summary> public bool genAudioClip(WorkerVars workerVars, DialogProgress dialogProgress) { int progessCount = 0; int episodeCount = 0; int totalEpisodes = workerVars.CombinedAll.Count; int curEpisodeCount = 0; int totalLines = UtilsSubs.getTotalLineCount(workerVars.CombinedAll); DateTime lastTime = UtilsSubs.getLastTime(workerVars.CombinedAll); UtilsName name = new UtilsName(Settings.Instance.DeckName, totalEpisodes, totalLines, lastTime, Settings.Instance.VideoClips.Size.Width, Settings.Instance.VideoClips.Size.Height); DialogProgress.updateProgressInvoke(dialogProgress, 0, "Creating audio clips."); // For each episode foreach (List <InfoCombined> combArray in workerVars.CombinedAll) { episodeCount++; // It is possible for all lines in an episode to be set to inactive if (combArray.Count == 0) { // Skip this episode continue; } // Is the audio input an mp3 file? bool inputFileIsMp3 = Settings.Instance.AudioClips.Files.Length > 0 && Path.GetExtension(Settings.Instance.AudioClips.Files[episodeCount - 1]) .ToLower() == ".mp3"; DateTime entireClipStartTime = combArray[0].Subs1.StartTime; DateTime entireClipEndTime = combArray[combArray.Count - 1].Subs1.EndTime; string tempMp3Filename = Path.GetTempPath() + ConstantSettings.TempAudioFilename; // Apply pad to entire clip timings (if requested) if (Settings.Instance.AudioClips.PadEnabled) { entireClipStartTime = UtilsSubs.applyTimePad(entireClipStartTime, -Settings.Instance.AudioClips.PadStart); entireClipEndTime = UtilsSubs.applyTimePad(entireClipEndTime, Settings.Instance.AudioClips.PadEnd); } // Do we need to extract the audio from the video file? if (Settings.Instance.AudioClips.UseAudioFromVideo) { string progressText = $"Extracting audio from video file {episodeCount} of {totalEpisodes}"; // {1} bool success = convertToMp3( Settings.Instance.VideoClips.Files[episodeCount - 1], Settings.Instance.VideoClips.AudioStream.Num, progressText, dialogProgress, entireClipStartTime, entireClipEndTime, tempMp3Filename); if (!success) { UtilsMsg.showErrMsg("Failed to extract the audio from the video.\n" + "Make sure that the video does not have any DRM restrictions."); return(false); } } // If the reencode option is set or the input audio is not an mp3, reencode to mp3 else if (ConstantSettings.ReencodeBeforeSplittingAudio || !inputFileIsMp3) { string progressText = $"Reencoding audio file {episodeCount} of {totalEpisodes}"; bool success = convertToMp3( Settings.Instance.AudioClips.Files[episodeCount - 1], "0", progressText, dialogProgress, entireClipStartTime, entireClipEndTime, tempMp3Filename); if (!success) { UtilsMsg.showErrMsg("Failed to reencode the audio file.\n" + "Make sure that the audio file does not have any DRM restrictions."); return(false); } } curEpisodeCount = 0; // Reset // For each line in episode, generate an audio clip foreach (InfoCombined comb in combArray) { progessCount++; curEpisodeCount++; int progress = Convert.ToInt32(progessCount * (100.0 / totalLines)); string progressText = $"Generating audio clip: {progessCount.ToString()} of {totalLines.ToString()}"; // Update the progress dialog DialogProgress.updateProgressInvoke(dialogProgress, progress, progressText); // Did the user press the cancel button? if (dialogProgress.Cancel) { File.Delete(tempMp3Filename); return(false); } DateTime startTime = comb.Subs1.StartTime; DateTime endTime = comb.Subs1.EndTime; DateTime filenameStartTime = comb.Subs1.StartTime; DateTime filenameEndTime = comb.Subs1.EndTime; string fileToCut = ""; if (Settings.Instance.AudioClips.UseAudioFromVideo || ConstantSettings.ReencodeBeforeSplittingAudio || !inputFileIsMp3) { startTime = UtilsSubs.shiftTiming(startTime, -(int)entireClipStartTime.TimeOfDay.TotalMilliseconds); endTime = UtilsSubs.shiftTiming(endTime, -(int)entireClipStartTime.TimeOfDay.TotalMilliseconds); fileToCut = tempMp3Filename; } else { fileToCut = Settings.Instance.AudioClips.Files[episodeCount - 1]; } // Apply pad (if requested) if (Settings.Instance.AudioClips.PadEnabled) { startTime = UtilsSubs.applyTimePad(startTime, -Settings.Instance.AudioClips.PadStart); endTime = UtilsSubs.applyTimePad(endTime, Settings.Instance.AudioClips.PadEnd); filenameStartTime = UtilsSubs.applyTimePad(comb.Subs1.StartTime, -Settings.Instance.AudioClips.PadStart); filenameEndTime = UtilsSubs.applyTimePad(comb.Subs1.EndTime, Settings.Instance.AudioClips.PadEnd); } string lyricSubs2 = ""; // Set the Subs2 lyric if it exists if (Settings.Instance.Subs[1].Files.Length != 0) { lyricSubs2 = comb.Subs2.Text.Trim(); } // Create output filename string nameStr = name.createName(ConstantSettings.AudioFilenameFormat, (int)episodeCount + Settings.Instance.EpisodeStartNumber - 1, progessCount, filenameStartTime, filenameEndTime, comb.Subs1.Text, lyricSubs2); string outName = $"{workerVars.MediaDir}{Path.DirectorySeparatorChar}{nameStr}"; // {2} // Create audio clip UtilsAudio.cutAudio(fileToCut, startTime, endTime, outName); // Tag the audio clip tagAudio(name, outName, episodeCount, curEpisodeCount, progessCount, combArray.Count, filenameStartTime, filenameEndTime, comb.Subs1.Text, lyricSubs2); } File.Delete(tempMp3Filename); } // Normalize all mp3 files in the media directory if (Settings.Instance.AudioClips.Normalize) { DialogProgress.updateProgressInvoke(dialogProgress, -1, "Normalizing audio..."); UtilsAudio.normalizeAudio(workerVars.MediaDir); } return(true); }
/// <summary> /// Parse the actors from the subtitle file (if possible) and populate the actors list. /// </summary> private void buttonActorCheck_Click(object sender, EventArgs e) { string[] subs1Files = null; string[] subs2Files = null; listBoxActors.Items.Clear(); if (radioButtonSubs1Actor.Checked) { if (subs1FilePattern.Length == 0) { UtilsMsg.showErrMsg("Can't check - Subs1 file isn't valid."); return; } else { subs1Files = UtilsCommon.getNonHiddenFiles(subs1FilePattern); if (subs1Files.Length > 0) { foreach (string f in subs1Files) { if (!isActorSupportedSubtitleFormat(f)) { UtilsMsg.showErrMsg("Can't check - Incorrect subtitle format found in Subs1 (only .ass/.ssa allowed)."); return; } } } else { UtilsMsg.showErrMsg("Can't check - No .ass/ssa files were found in Subs1."); return; } } } else { if (subs2FilePattern.Length == 0) { UtilsMsg.showErrMsg("Can't check - Subs2 file isn't valid."); return; } else { subs2Files = UtilsCommon.getNonHiddenFiles(subs2FilePattern); if (subs2Files.Length > 0) { foreach (string f in subs2Files) { if (!isActorSupportedSubtitleFormat(f)) { UtilsMsg.showErrMsg("Can't check - Incorrect subtitle format found in Subs2 (only .ass/.ssa allowed)."); return; } } } else { UtilsMsg.showErrMsg("Can't check - No .ass/ssa files were found in Subs2."); return; } } } string[] fileList = null; Encoding fileEncoding; int subsNum = 1; if (radioButtonSubs1Actor.Checked) { subsNum = 1; fileList = subs1Files; fileEncoding = Encoding.GetEncoding(InfoEncoding.longToShort(this.subs1Encoding)); } else { subsNum = 2; fileList = subs2Files; fileEncoding = Encoding.GetEncoding(InfoEncoding.longToShort(this.subs2Encoding)); } List <string> actorList = new List <string>(); // Get list of actors from all episodes foreach (string file in fileList) { SubsParser subsParser = new SubsParserASS(null, file, fileEncoding, subsNum); List <InfoLine> subsLineInfos = subsParser.parse(); foreach (InfoLine info in subsLineInfos) { string actor = info.Actor.Trim(); if (!actorList.Contains(actor)) { actorList.Add(actor); } } } foreach (string actor in actorList) { string addActor = actor; listBoxActors.Items.Add(addActor); } for (int i = 0; i < listBoxActors.Items.Count; i++) { listBoxActors.SetSelected(i, true); } }
/// <summary> /// Update GUI based on global settings. /// </summary> private void updateGUI() { try { textBoxSubs1IncludedWords.Text = UtilsCommon.makeSemiString(Settings.Instance.Subs[0].IncludedWords); textBoxSubs1ExcludedWords.Text = UtilsCommon.makeSemiString(Settings.Instance.Subs[0].ExcludedWords); checkBoxSubs1RemoveStyledLines.Checked = Settings.Instance.Subs[0].RemoveStyledLines; checkBoxSubs1RemovedNoCounterpart.Checked = Settings.Instance.Subs[0].RemoveNoCounterpart; checkBoxSubs1ExcludeDuplicateLines.Checked = Settings.Instance.Subs[0].ExcludeDuplicateLinesEnabled; checkBoxSubs1ExcludeFewer.Checked = Settings.Instance.Subs[0].ExcludeFewerEnabled; numericUpDownSubs1ExcludeFewer.Value = (decimal)Settings.Instance.Subs[0].ExcludeFewerCount; checkBoxSubs1ExcludeShorterThanTime.Checked = Settings.Instance.Subs[0].ExcludeShorterThanTimeEnabled; numericUpDownSubs1ExcludeShorterThanTime.Value = (decimal)Settings.Instance.Subs[0].ExcludeShorterThanTime; checkBoxSubs1ExcludeLongerThanTime.Checked = Settings.Instance.Subs[0].ExcludeLongerThanTimeEnabled; numericUpDownSubs1ExcludeLongerThanTime.Value = (decimal)Settings.Instance.Subs[0].ExcludeLongerThanTime; checkBoxSubs1JoinSentences.Checked = Settings.Instance.Subs[0].JoinSentencesEnabled; textBoxSubs1JoinSentenceChars.Text = Settings.Instance.Subs[0].JoinSentencesCharList; radioButtonSubs1Actor.Checked = Settings.Instance.Subs[0].ActorsEnabled; textBoxSubs2IncludedWords.Text = UtilsCommon.makeSemiString(Settings.Instance.Subs[1].IncludedWords); textBoxSubs2ExcludedWords.Text = UtilsCommon.makeSemiString(Settings.Instance.Subs[1].ExcludedWords); checkBoxSubs2RemoveNoCounterpart.Checked = Settings.Instance.Subs[1].RemoveNoCounterpart; checkBoxSubs2RemoveStyledLines.Checked = Settings.Instance.Subs[1].RemoveStyledLines; checkBoxSubs2ExcludeDuplicateLines.Checked = Settings.Instance.Subs[1].ExcludeDuplicateLinesEnabled; checkBoxSubs2ExcludeFewer.Checked = Settings.Instance.Subs[1].ExcludeFewerEnabled; numericUpDownSubs2ExcludeFewer.Value = (decimal)Settings.Instance.Subs[1].ExcludeFewerCount; checkBoxSubs2ExcludeShorterThanTime.Checked = Settings.Instance.Subs[1].ExcludeShorterThanTimeEnabled; numericUpDownSubs2ExcludeShorterThanTime.Value = Settings.Instance.Subs[1].ExcludeShorterThanTime; checkBoxSubs2ExcludeLongerThanTime.Checked = Settings.Instance.Subs[1].ExcludeLongerThanTimeEnabled; numericUpDownSubs2ExcludeLongerThanTime.Value = Settings.Instance.Subs[1].ExcludeLongerThanTime; checkBoxSubs2JoinSentences.Checked = Settings.Instance.Subs[1].JoinSentencesEnabled; textBoxSubs2JoinSentenceChars.Text = Settings.Instance.Subs[1].JoinSentencesCharList; radioButtonSubs2Actor.Checked = Settings.Instance.Subs[1].ActorsEnabled; numericUpDownContextLeading.Value = (decimal)Settings.Instance.ContextLeadingCount; checkBoxLeadingIncludeAudioClips.Checked = Settings.Instance.ContextLeadingIncludeAudioClips; checkBoxLeadingIncludeSnapshots.Checked = Settings.Instance.ContextLeadingIncludeSnapshots; checkBoxLeadingIncludeVideoClips.Checked = Settings.Instance.ContextLeadingIncludeVideoClips; numericUpDownLeadingRange.Value = (decimal)Settings.Instance.ContextLeadingRange; numericUpDownContextTrailing.Value = (decimal)Settings.Instance.ContextTrailingCount; checkBoxTrailingIncludeAudioClips.Checked = Settings.Instance.ContextTrailingIncludeAudioClips; checkBoxTrailingIncludeSnapshots.Checked = Settings.Instance.ContextTrailingIncludeSnapshots; checkBoxTrailingIncludeVideoClips.Checked = Settings.Instance.ContextTrailingIncludeVideoClips; numericUpDownTrailingRange.Value = (decimal)Settings.Instance.ContextTrailingRange; checkBoxJapKanjiOnly.Checked = Settings.Instance.LangaugeSpecific.KanjiLinesOnly; groupBoxCheckVobsubColors.Checked = Settings.Instance.VobSubColors.Enabled; panelColorBackground.BackColor = Settings.Instance.VobSubColors.Colors[0]; panelColorText.BackColor = Settings.Instance.VobSubColors.Colors[1]; panelColorOutline.BackColor = Settings.Instance.VobSubColors.Colors[2]; panelColorAntialias.BackColor = Settings.Instance.VobSubColors.Colors[3]; checkBoxColorBackground.Checked = Settings.Instance.VobSubColors.TransparencyEnabled[0]; checkBoxColorText.Checked = Settings.Instance.VobSubColors.TransparencyEnabled[1]; checkBoxColorOutline.Checked = Settings.Instance.VobSubColors.TransparencyEnabled[2]; checkBoxColorAntialias.Checked = Settings.Instance.VobSubColors.TransparencyEnabled[3]; } catch (Exception e1) { UtilsMsg.showErrMsg("Could not completely fill in all settings for this dialog.\n" + "Did you load a file saved from a previous version?\n\n" + e1); } }
/// <summary> /// Performs the work in the processing thread. /// </summary> private void bw_DoWork(object sender, DoWorkEventArgs e) { WorkerVars workerVars = e.Argument as WorkerVars; List <List <InfoCombined> > combinedAll = new List <List <InfoCombined> >(); WorkerSubs subsWorker = new WorkerSubs(); int totalLines = 0; bool needToGenerateCombinedAll = workerVars.CombinedAll == null; // Only generate a combinedAll if one if not provided if (needToGenerateCombinedAll) { // Parse and combine the subtitles try { DialogProgress.nextStepInvoke(dialogProgress, ++currentStep, "Combine subs"); combinedAll = subsWorker.combineAllSubs(workerVars, dialogProgress); if (combinedAll != null) { workerVars.CombinedAll = combinedAll; } else { e.Cancel = true; return; } } catch (Exception e1) { UtilsMsg.showErrMsg("Something went wrong before processing could start.\n" + e1); e.Cancel = true; return; } foreach (List <InfoCombined> combArray in workerVars.CombinedAll) { totalLines += combArray.Count; } if (totalLines == 0) { UtilsMsg.showErrMsg( "No lines of dialog could be parsed from the subtitle files.\nPlease check that they are valid."); e.Cancel = true; return; } // Inactivate lines try { DialogProgress.nextStepInvoke(dialogProgress, ++currentStep, "Inactivate lines"); combinedAll = subsWorker.inactivateLines(workerVars, dialogProgress); if (combinedAll != null) { workerVars.CombinedAll = combinedAll; } else { e.Cancel = true; return; } } catch (Exception e1) { UtilsMsg.showErrMsg("Something went wrong while setting active lines.\n" + e1); e.Cancel = true; return; } } // Find context lines if (Settings.Instance.ContextLeadingCount > 0 || Settings.Instance.ContextTrailingCount > 0) { try { DialogProgress.nextStepInvoke(dialogProgress, ++currentStep, "Find context lines"); combinedAll = subsWorker.markLinesOnlyNeededForContext(workerVars, dialogProgress); if (combinedAll != null) { workerVars.CombinedAll = combinedAll; } else { e.Cancel = true; return; } } catch (Exception e1) { UtilsMsg.showErrMsg("Something went wrong while finding context lines.\n" + e1); e.Cancel = true; return; } } // Remove Inactive lines (unless they are needed for context) try { DialogProgress.nextStepInvoke(dialogProgress, ++currentStep, "Remove inactive lines"); combinedAll = subsWorker.removeInactiveLines(workerVars, dialogProgress, true); if (combinedAll != null) { workerVars.CombinedAll = combinedAll; } else { e.Cancel = true; return; } } catch (Exception e1) { UtilsMsg.showErrMsg("Something went wrong while removing inactive lines.\n" + e1); e.Cancel = true; return; } totalLines = 0; foreach (List <InfoCombined> combArray in workerVars.CombinedAll) { totalLines += combArray.Count; } if (totalLines == 0) { UtilsMsg.showErrMsg( "No lines will be processed. Please check your settings to make\nsure that you are not mistakenly pruning too many lines."); e.Cancel = true; return; } try { // Move vobsubs from preview dir to .media dir if (!needToGenerateCombinedAll) { if (!subsWorker.copyVobsubsFromPreviewDirToMediaDir(workerVars, dialogProgress)) { e.Cancel = true; return; } } } catch { } // Generate SRS import file try { DialogProgress.nextStepInvoke(dialogProgress, ++currentStep, "Generate import file"); WorkerSrs srsWorker = new WorkerSrs(); if (!srsWorker.genSrs(workerVars, dialogProgress)) { e.Cancel = true; return; } } catch (Exception e1) { UtilsMsg.showErrMsg("Something went wrong while generating the SRS import file.\n" + e1); e.Cancel = true; return; } List <List <InfoCombined> > combinedAllWithContext = ObjectCopier.Clone <List <List <InfoCombined> > >(workerVars.CombinedAll); // Generate audio clips try { if (Settings.Instance.AudioClips.Enabled) { DialogProgress.nextStepInvoke(dialogProgress, ++currentStep, "Generate audio clips"); if (Settings.Instance.ContextLeadingCount > 0 && Settings.Instance.ContextLeadingIncludeAudioClips || Settings.Instance.ContextTrailingCount > 0 && Settings.Instance.ContextTrailingIncludeAudioClips) { workerVars.CombinedAll = combinedAllWithContext; } else { workerVars.CombinedAll = subsWorker.removeContextOnlyLines(combinedAllWithContext); } WorkerAudio audioWorker = new WorkerAudio(); if (!audioWorker.genAudioClip(workerVars, dialogProgress)) { e.Cancel = true; return; } } } catch (Exception e1) { UtilsMsg.showErrMsg("Something went wrong while generating the audio clips.\n" + e1); e.Cancel = true; return; } // Generate Snapshots try { if (Settings.Instance.Snapshots.Enabled) { DialogProgress.nextStepInvoke(dialogProgress, ++currentStep, "Generate snapshots"); if (Settings.Instance.ContextLeadingCount > 0 && Settings.Instance.ContextLeadingIncludeSnapshots || Settings.Instance.ContextTrailingCount > 0 && Settings.Instance.ContextTrailingIncludeSnapshots) { workerVars.CombinedAll = combinedAllWithContext; } else { workerVars.CombinedAll = subsWorker.removeContextOnlyLines(combinedAllWithContext); } WorkerSnapshot snapshotWorker = new WorkerSnapshot(); if (!snapshotWorker.genSnapshots(workerVars, dialogProgress)) { e.Cancel = true; return; } } } catch (Exception e1) { UtilsMsg.showErrMsg("Something went wrong while generating snapshots.\n" + e1); e.Cancel = true; return; } // Generate video clips try { if (Settings.Instance.VideoClips.Enabled) { DialogProgress.nextStepInvoke(dialogProgress, ++currentStep, "Generate video clips"); if (Settings.Instance.ContextLeadingCount > 0 && Settings.Instance.ContextLeadingIncludeVideoClips || Settings.Instance.ContextTrailingCount > 0 && Settings.Instance.ContextTrailingIncludeVideoClips) { workerVars.CombinedAll = combinedAllWithContext; } else { workerVars.CombinedAll = subsWorker.removeContextOnlyLines(combinedAllWithContext); } WorkerVideo videoWorker = new WorkerVideo(); if (!videoWorker.genVideoClip(workerVars, dialogProgress)) { e.Cancel = true; return; } } } catch (Exception e1) { UtilsMsg.showErrMsg("Something went wrong while generating the video clips.\n" + e1); e.Cancel = true; return; } e.Result = workerVars; }