public void ExtractMKVSegments(String argMKVFile, List <gMKVSegment> argMKVSegmentsToExtract, String argOutputDirectory, MkvChapterTypes argChapterType, TimecodesExtractionMode argTimecodesExtractionMode, CuesExtractionMode argCueExtractionMode) { _Abort = false; _AbortAll = false; _ErrorBuilder.Length = 0; _MKVExtractOutput.Length = 0; // Analyze the MKV segments and get the initial parameters List <TrackParameter> initialParameters = new List <TrackParameter>(); foreach (gMKVSegment seg in argMKVSegmentsToExtract) { if (_AbortAll) { _ErrorBuilder.AppendLine("User aborted all the processes!"); break; } try { initialParameters.AddRange(GetTrackParameters(seg, argMKVFile, argOutputDirectory, argChapterType, argTimecodesExtractionMode, argCueExtractionMode)); } catch (Exception ex) { Debug.WriteLine(ex); _ErrorBuilder.AppendLine(String.Format("Segment: {0}\r\nException: {1}\r\n", seg, ex.Message)); } } // Group the initial parameters, in order to batch extract the mkv segments List <TrackParameter> finalParameters = new List <TrackParameter>(); foreach (TrackParameter initPar in initialParameters) { TrackParameter currentPar = null; foreach (TrackParameter finalPar in finalParameters) { if (finalPar.ExtractMode == initPar.ExtractMode) { currentPar = finalPar; break; } } if (currentPar != null) { currentPar.TrackOutput = String.Format("{0} {1}", currentPar.TrackOutput, initPar.TrackOutput); } else { finalParameters.Add(initPar); } } // Time to extract the mkv segments foreach (TrackParameter finalPar in finalParameters) { if (_AbortAll) { _ErrorBuilder.AppendLine("User aborted all the processes!"); break; } try { if (finalPar.WriteOutputToFile) { _OutputFileWriter = new StreamWriter(finalPar.OutputFilename, false, new UTF8Encoding(false, true)); } OnMkvExtractTrackUpdated(Enum.GetName(finalPar.ExtractMode.GetType(), finalPar.ExtractMode)); ExtractMkvSegment(argMKVFile, String.Format("{0} {1} \"{2}\" {3}", Enum.GetName(finalPar.ExtractMode.GetType(), finalPar.ExtractMode), finalPar.Options, argMKVFile, finalPar.TrackOutput), finalPar.WriteOutputToFile); } catch (Exception ex) { Debug.WriteLine(ex); _ErrorBuilder.AppendLine(String.Format("Track output: {0}\r\nException: {1}\r\n", finalPar.TrackOutput, ex.Message)); } finally { if (finalPar.WriteOutputToFile) { _OutputFileWriter.Close(); _OutputFileWriter = null; try { // If we have chapters with CUE format, then we read the XML chapters and convert it to CUE if (finalPar.ExtractMode == MkvExtractModes.chapters) { if (finalPar.OutputFilename.EndsWith("cue")) { Chapters c = null; using (StreamReader sr = new StreamReader(finalPar.OutputFilename)) { XmlSerializer serializer = new XmlSerializer(typeof(Chapters)); c = (Chapters)serializer.Deserialize(sr); } Cue cue = new Cue(); cue.File = Path.GetFileName(argMKVFile); cue.FileType = "WAVE"; cue.Title = Path.GetFileName(argMKVFile); cue.Tracks = new List <CueTrack>(); if (c.EditionEntry != null && c.EditionEntry.Length > 0 && c.EditionEntry[0].ChapterAtom != null && c.EditionEntry[0].ChapterAtom.Length > 0) { Int32 currentChapterTrackNumber = 1; foreach (ChapterAtom atom in c.EditionEntry[0].ChapterAtom) { CueTrack tr = new CueTrack(); tr.Number = currentChapterTrackNumber; if (atom.ChapterDisplay != null && atom.ChapterDisplay.Length > 0) { tr.Title = atom.ChapterDisplay[0].ChapterString; } if (!String.IsNullOrEmpty(atom.ChapterTimeStart) && atom.ChapterTimeStart.Contains(":")) { String[] timeElements = atom.ChapterTimeStart.Split(new String[] { ":" }, StringSplitOptions.None); if (timeElements.Length == 3) { // Find cue minutes from hours and minutes Int32 hours = Int32.Parse(timeElements[0]); Int32 minutes = Int32.Parse(timeElements[1]) + 60 * hours; // Convert nanoseconds to frames (each second is 75 frames) Int64 nanoSeconds = 0; Int32 frames = 0; Int32 secondsLength = timeElements[2].Length; if (timeElements[2].Contains(".")) { secondsLength = timeElements[2].IndexOf("."); nanoSeconds = Int64.Parse(timeElements[2].Substring(timeElements[2].IndexOf(".") + 1)); // I take the integer part of the result action in order to get the first frame frames = Convert.ToInt32(Math.Floor(Convert.ToDouble(nanoSeconds) / 1000000000.0 * 75.0)); } tr.Index = String.Format("{0}:{1}:{2}", minutes.ToString("#00") , timeElements[2].Substring(0, secondsLength) , frames.ToString("00") ); } } cue.Tracks.Add(tr); currentChapterTrackNumber++; } } StringBuilder cueBuilder = new StringBuilder(); cueBuilder.AppendFormat("REM GENRE \"\"\r\n"); cueBuilder.AppendFormat("REM DATE \"\"\r\n"); cueBuilder.AppendFormat("PERFORMER \"\"\r\n"); cueBuilder.AppendFormat("TITLE \"{0}\"\r\n", cue.Title); cueBuilder.AppendFormat("FILE \"{0}\" {1}\r\n", cue.File, cue.FileType); foreach (CueTrack tr in cue.Tracks) { cueBuilder.AppendFormat("\tTRACK {0} AUDIO\r\n", tr.Number.ToString("00")); cueBuilder.AppendFormat("\t\tTITLE \"{0}\"\r\n", tr.Title); cueBuilder.AppendFormat("\t\tPERFORMER \"\"\r\n"); cueBuilder.AppendFormat("\t\tINDEX 01 {0}\r\n", tr.Index); } using (StreamWriter sw = new StreamWriter(finalPar.OutputFilename, false, Encoding.UTF8)) { sw.Write(cueBuilder.ToString()); } } } } catch (Exception exc) { Debug.WriteLine(exc); _ErrorBuilder.AppendLine(String.Format("Track output: {0}\r\nException: {1}\r\n", finalPar.TrackOutput, exc.Message)); } } } } // check for errors if (_ErrorBuilder.Length > 0) { throw new Exception(_ErrorBuilder.ToString()); } }
public void Reload() { if (!File.Exists(Path.Combine(_ApplicationPath, _SETTINGS_FILE))) { Save(); } else { using (StreamReader sr = new StreamReader(Path.Combine(_ApplicationPath, _SETTINGS_FILE), Encoding.UTF8)) { String line = String.Empty; while ((line = sr.ReadLine()) != null) { if (line.StartsWith("MKVToolnix Path:")) { try { _MkvToolnixPath = line.Substring(line.IndexOf(":") + 1); } catch (Exception ex) { Debug.WriteLine(ex); _MkvToolnixPath = String.Empty; } } else if (line.StartsWith("Chapter Type:")) { try { _ChapterType = (MkvChapterTypes)Enum.Parse(typeof(MkvChapterTypes), line.Substring(line.IndexOf(":") + 1)); } catch (Exception ex) { Debug.WriteLine(ex); _ChapterType = MkvChapterTypes.XML; } } else if (line.StartsWith("Output Directory:")) { try { _OutputDirectory = line.Substring(line.IndexOf(":") + 1); } catch (Exception ex) { Debug.WriteLine(ex); _OutputDirectory = String.Empty; } } else if (line.StartsWith("Lock Output Directory:")) { try { _LockedOutputDirectory = Boolean.Parse(line.Substring(line.IndexOf(":") + 1)); } catch (Exception ex) { Debug.WriteLine(ex); _LockedOutputDirectory = false; } } else if (line.StartsWith("Initial Window Position X:")) { try { _WindowPosX = Int32.Parse(line.Substring(line.IndexOf(":") + 1)); } catch (Exception ex) { Debug.WriteLine(ex); _WindowPosX = 0; } } else if (line.StartsWith("Initial Window Position Y:")) { try { _WindowPosY = Int32.Parse(line.Substring(line.IndexOf(":") + 1)); } catch (Exception ex) { Debug.WriteLine(ex); _WindowPosY = 0; } } else if (line.StartsWith("Initial Window Size Width:")) { try { _WindowSizeWidth = Int32.Parse(line.Substring(line.IndexOf(":") + 1)); } catch (Exception ex) { Debug.WriteLine(ex); _WindowSizeWidth = 640; } } else if (line.StartsWith("Initial Window Size Height:")) { try { _WindowSizeHeight = Int32.Parse(line.Substring(line.IndexOf(":") + 1)); } catch (Exception ex) { Debug.WriteLine(ex); _WindowSizeHeight = 600; } } else if (line.StartsWith("Job Mode:")) { try { _JobMode = Boolean.Parse(line.Substring(line.IndexOf(":") + 1)); } catch (Exception ex) { Debug.WriteLine(ex); _JobMode = false; } } else if (line.StartsWith("Window State:")) { try { _WindowState = (FormWindowState)Enum.Parse(typeof(FormWindowState), line.Substring(line.IndexOf(":") + 1), true); } catch (Exception ex) { Debug.WriteLine(ex); _WindowSizeHeight = 600; } } else if (line.StartsWith("Show Popup:")) { try { _ShowPopup = Boolean.Parse(line.Substring(line.IndexOf(":") + 1)); } catch (Exception ex) { Debug.WriteLine(ex); _ShowPopup = true; } } else if (line.StartsWith("Show Popup In Job Manager:")) { try { _ShowPopupInJobManager = Boolean.Parse(line.Substring(line.IndexOf(":") + 1)); } catch (Exception ex) { Debug.WriteLine(ex); _ShowPopup = true; } } } } } }
private List <TrackParameter> GetTrackParameters(gMKVSegment argSeg, String argMKVFile, String argOutputDirectory, MkvChapterTypes argChapterType, TimecodesExtractionMode argTimecodesExtractionMode, CuesExtractionMode argCueExtractionMode) { // create the new parameter list type List <TrackParameter> trackParameterList = new List <TrackParameter>(); // check the selected segment's type if (argSeg is gMKVTrack) { // if we are in a mode that requires timecodes extraction, add the parameter for the track if (argTimecodesExtractionMode != TimecodesExtractionMode.NoTimecodes) { trackParameterList.Add(new TrackParameter( MkvExtractModes.timecodes_v2, String.Empty, String.Format("{0}:\"{1}\"", ((gMKVTrack)argSeg).TrackID, Path.Combine( argOutputDirectory, String.Format("{0}_track{1}_{2}.tc.txt", Path.GetFileNameWithoutExtension(argMKVFile), ((gMKVTrack)argSeg).TrackNumber, ((gMKVTrack)argSeg).Language))), false, String.Empty )); } // if we are in a mode that requires cues extraction, add the parameter for the track if (argCueExtractionMode != CuesExtractionMode.NoCues) { trackParameterList.Add(new TrackParameter( MkvExtractModes.cues, String.Empty, String.Format("{0}:\"{1}\"", ((gMKVTrack)argSeg).TrackID, Path.Combine( argOutputDirectory, String.Format("{0}_track{1}_{2}.cue", Path.GetFileNameWithoutExtension(argMKVFile), ((gMKVTrack)argSeg).TrackNumber, ((gMKVTrack)argSeg).Language))), false, String.Empty )); } // check if the mode requires the extraction of the segment itself if ( !( (argTimecodesExtractionMode == TimecodesExtractionMode.OnlyTimecodes && argCueExtractionMode == CuesExtractionMode.NoCues) || (argTimecodesExtractionMode == TimecodesExtractionMode.NoTimecodes && argCueExtractionMode == CuesExtractionMode.OnlyCues) ) || (argTimecodesExtractionMode == TimecodesExtractionMode.OnlyTimecodes && argCueExtractionMode == CuesExtractionMode.OnlyCues) ) { String outputFileExtension = String.Empty; String outputDelayPart = String.Empty; // check the track's type in order to get the output file's extension and the delay for audio tracks switch (((gMKVTrack)argSeg).TrackType) { case MkvTrackType.video: // get the extension of the output via the CODEC_ID of the track outputFileExtension = getVideoFileExtensionFromCodecID((gMKVTrack)argSeg); break; case MkvTrackType.audio: // add the delay to the extraOutput for the track filename outputDelayPart = String.Format("_DELAY {0}ms", ((gMKVTrack)argSeg).EffectiveDelay.ToString(CultureInfo.InvariantCulture)); // get the extension of the output via the CODEC_ID of the track outputFileExtension = getAudioFileExtensionFromCodecID((gMKVTrack)argSeg); break; case MkvTrackType.subtitles: // get the extension of the output via the CODEC_ID of the track outputFileExtension = getSubtitleFileExtensionFromCodecID((gMKVTrack)argSeg); break; default: break; } // add the parameter for extracting the track trackParameterList.Add(new TrackParameter( MkvExtractModes.tracks, String.Empty, String.Format("{0}:\"{1}\"", ((gMKVTrack)argSeg).TrackID, Path.Combine( argOutputDirectory, String.Format("{0}_track{1}_{2}{3}.{4}", Path.GetFileNameWithoutExtension(argMKVFile), ((gMKVTrack)argSeg).TrackNumber, ((gMKVTrack)argSeg).Language, outputDelayPart, outputFileExtension))), false, String.Empty )); } } else if (argSeg is gMKVAttachment) { // check if the mode requires the extraction of the segment itself if ( !( (argTimecodesExtractionMode == TimecodesExtractionMode.OnlyTimecodes && argCueExtractionMode == CuesExtractionMode.NoCues) || (argTimecodesExtractionMode == TimecodesExtractionMode.NoTimecodes && argCueExtractionMode == CuesExtractionMode.OnlyCues) ) || (argTimecodesExtractionMode == TimecodesExtractionMode.OnlyTimecodes && argCueExtractionMode == CuesExtractionMode.OnlyCues) ) { // add the parameter for extracting the attachment trackParameterList.Add(new TrackParameter( MkvExtractModes.attachments, String.Empty, String.Format("{0}:\"{1}\"", ((gMKVAttachment)argSeg).ID, Path.Combine( argOutputDirectory, ((gMKVAttachment)argSeg).Filename)), false, String.Empty )); } } else if (argSeg is gMKVChapter) { // check if the mode requires the extraction of the segment itself if ( !( (argTimecodesExtractionMode == TimecodesExtractionMode.OnlyTimecodes && argCueExtractionMode == CuesExtractionMode.NoCues) || (argTimecodesExtractionMode == TimecodesExtractionMode.NoTimecodes && argCueExtractionMode == CuesExtractionMode.OnlyCues) ) || (argTimecodesExtractionMode == TimecodesExtractionMode.OnlyTimecodes && argCueExtractionMode == CuesExtractionMode.OnlyCues) ) { String outputFileExtension = String.Empty; String options = String.Empty; // check the chapter's type to determine the output file's extension and options switch (argChapterType) { case MkvChapterTypes.XML: outputFileExtension = "xml"; break; case MkvChapterTypes.OGM: outputFileExtension = "ogm.txt"; options = "--simple"; break; case MkvChapterTypes.CUE: outputFileExtension = "cue"; break; default: break; } // add the parameter for extracting the chapters trackParameterList.Add(new TrackParameter( MkvExtractModes.chapters, options, String.Empty, true, Path.Combine( argOutputDirectory, String.Format("{0}_chapters.{1}", Path.GetFileNameWithoutExtension(argMKVFile), outputFileExtension)) )); } } return(trackParameterList); }