diff --git a/GARbro.GUI.csproj b/GARbro.GUI.csproj
index 425618ff..f093885b 100644
--- a/GARbro.GUI.csproj
+++ b/GARbro.GUI.csproj
@@ -140,7 +140,6 @@
ExtractFile.xaml
-
diff --git a/GarAudio.cs b/GarAudio.cs
deleted file mode 100644
index 273695e2..00000000
--- a/GarAudio.cs
+++ /dev/null
@@ -1,71 +0,0 @@
-//! \file GarAudio.cs
-//! \date Thu May 14 13:58:03 2015
-//! \brief GARbro audio formats conversions.
-//
-// Copyright (C) 2015 by morkt
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to
-// deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-// IN THE SOFTWARE.
-//
-
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Windows;
-using GameRes;
-using GARbro.GUI.Strings;
-
-namespace GARbro.GUI
-{
- public partial class MainWindow : Window
- {
- void ExtractAudio (ArcFile arc, Entry entry)
- {
- using (var file = arc.OpenEntry (entry))
- using (var sound = AudioFormat.Read (file))
- {
- if (null == sound)
- throw new InvalidFormatException (string.Format ("{1}: {0}", guiStrings.MsgUnableInterpret, entry.Name));
- ConvertAudio (entry.Name, sound);
- }
- }
-
- public static readonly HashSet CommonAudioFormats = new HashSet { "wav", "mp3", "ogg" };
-
- void ConvertAudio (string entry_name, SoundInput input)
- {
- string source_format = input.SourceFormat;
- if (CommonAudioFormats.Contains (source_format))
- {
- string output_name = Path.ChangeExtension (entry_name, source_format);
- using (var output = ArchiveFormat.CreateFile (output_name))
- {
- input.Source.Position = 0;
- input.Source.CopyTo (output);
- }
- }
- else
- {
- var wav_format = FormatCatalog.Instance.AudioFormats.Where (f => f.Tag == "WAV").First();
- string output_name = Path.ChangeExtension (entry_name, "wav");
- using (var output = ArchiveFormat.CreateFile (output_name))
- wav_format.Write (input, output);
- }
- }
- }
-}
diff --git a/GarExtract.cs b/GarExtract.cs
index 49044755..3ffe8f43 100644
--- a/GarExtract.cs
+++ b/GarExtract.cs
@@ -27,6 +27,7 @@ using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
+using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using System.Windows.Input;
@@ -62,59 +63,105 @@ namespace GARbro.GUI
// extract into directory named after archive
if (!string.IsNullOrEmpty (Path.GetExtension (entry.Name)))
destination = Path.GetFileNameWithoutExtension (source);
- ExtractArchive (source, destination);
+ using (var extractor = new GarExtract (this, source))
+ extractor.ExtractAll (destination);
}
}
else if (null != m_app.CurrentArchive)
{
var vm = ViewModel as ArchiveViewModel;
string destination = Path.GetDirectoryName (vm.Path);
- string arc_name = Path.GetFileName (vm.Path);
- if (null == entry || (entry.Name == ".." && vm.SubDir == "")) // root entry
+ using (var extractor = new GarExtract (this, vm.Path, m_app.CurrentArchive))
{
- ExtractArchive (m_app.CurrentArchive, arc_name, destination);
- }
- else
- {
- ExtractFileFromArchive (entry, destination);
+ if (null == entry || (entry.Name == ".." && vm.SubDir == "")) // root entry
+ extractor.ExtractAll (destination);
+ else
+ extractor.Extract (entry, destination);
}
}
}
+ catch (OperationCanceledException X)
+ {
+ SetStatusText (X.Message);
+ }
catch (Exception X)
{
PopupError (X.Message, guiStrings.MsgErrorExtracting);
}
}
+ }
- private void ExtractArchive (string path, string destination)
+ sealed internal class GarExtract : IDisposable
+ {
+ private MainWindow m_main;
+ private string m_arc_name;
+ private ArcFile m_arc;
+ private readonly bool m_should_dispose;
+ private bool m_skip_images = false;
+ private bool m_skip_script = false;
+ private bool m_skip_audio = false;
+ private bool m_convert_audio;
+ private ImageFormat m_image_format;
+ private IEnumerable m_file_list;
+ private int m_extract_count;
+ private bool m_extract_in_progress = false;
+ private ProgressDialog m_progress_dialog;
+ private Exception m_pending_error;
+
+ public static readonly HashSet CommonAudioFormats = new HashSet { "wav", "mp3", "ogg" };
+
+ public GarExtract (MainWindow parent, string source)
{
- string arc_name = Path.GetFileName (path);
+ m_main = parent;
+ m_arc_name = Path.GetFileName (source);
FormatCatalog.Instance.LastError = null;
- var arc = ArcFile.TryOpen (path);
- if (null != arc)
- {
- ExtractArchive (arc, arc_name, destination);
- }
- else
+ m_arc = ArcFile.TryOpen (source);
+ if (null == m_arc)
{
string error_message;
if (FormatCatalog.Instance.LastError != null)
error_message = FormatCatalog.Instance.LastError.Message;
else
error_message = guiStrings.MsgUnknownFormat;
- SetStatusText (string.Format ("{1}: {0}", error_message, arc_name));
+ throw new OperationCanceledException (string.Format ("{1}: {0}", error_message, m_arc_name));
+ }
+ m_should_dispose = true;
+ }
+
+ public GarExtract (MainWindow parent, string source, ArcFile arc)
+ {
+ m_main = parent;
+ m_arc_name = Path.GetFileName (source);
+ m_arc = arc;
+ m_should_dispose = false;
+ }
+
+ private void PrepareDestination (string destination)
+ {
+ bool stop_watch = !m_main.ViewModel.IsArchive;
+ if (stop_watch)
+ m_main.StopWatchDirectoryChanges();
+ try
+ {
+ Directory.CreateDirectory (destination);
+ Directory.SetCurrentDirectory (destination);
+ }
+ finally
+ {
+ if (stop_watch)
+ m_main.ResumeWatchDirectoryChanges();
}
}
- private void ExtractArchive (ArcFile arc, string arc_name, string destination)
+ public void ExtractAll (string destination)
{
- if (0 == arc.Dir.Count)
+ if (0 == m_arc.Dir.Count)
{
- SetStatusText (string.Format ("{1}: {0}", guiStrings.MsgEmptyArchive, arc_name));
+ m_main.SetStatusText (string.Format ("{1}: {0}", guiStrings.MsgEmptyArchive, m_arc_name));
return;
}
- var extractDialog = new ExtractArchiveDialog (arc_name, destination);
- extractDialog.Owner = this;
+ var extractDialog = new ExtractArchiveDialog (m_arc_name, destination);
+ extractDialog.Owner = m_main;
var result = extractDialog.ShowDialog();
if (!result.Value)
return;
@@ -123,135 +170,219 @@ namespace GARbro.GUI
if (!string.IsNullOrEmpty (destination))
{
destination = Path.GetFullPath (destination);
- Trace.WriteLine (destination, "Extract destination");
- StopWatchDirectoryChanges();
- try
- {
- Directory.CreateDirectory (destination);
- Directory.SetCurrentDirectory (destination);
- }
- finally
- {
- ResumeWatchDirectoryChanges();
- }
+ PrepareDestination (destination);
}
- IEnumerable file_list = arc.Dir;
- bool skip_images = !extractDialog.ExtractImages.IsChecked.Value;
- bool skip_script = !extractDialog.ExtractText.IsChecked.Value;
- bool skip_audio = !extractDialog.ExtractAudio.IsChecked.Value;
- if (skip_images || skip_script || skip_audio)
- file_list = file_list.Where (f => !(skip_images && f.Type == "image") &&
- !(skip_script && f.Type == "script") &&
- !(skip_audio && f.Type == "audio"));
+ else
+ destination = ".";
+ m_skip_images = !extractDialog.ExtractImages.IsChecked.Value;
+ m_skip_script = !extractDialog.ExtractText.IsChecked.Value;
+ m_skip_audio = !extractDialog.ExtractAudio.IsChecked.Value;
+ if (!m_skip_images)
+ m_image_format = extractDialog.GetImageFormat (extractDialog.ImageConversionFormat);
- if (!file_list.Any())
- {
- SetStatusText (string.Format ("{1}: {0}", guiStrings.MsgNoFiles, arc_name));
- return;
- }
- ImageFormat image_format = null;
- if (!skip_images)
- image_format = extractDialog.GetImageFormat (extractDialog.ImageConversionFormat);
-
- SetStatusText (string.Format(guiStrings.MsgExtractingTo, arc_name, destination));
- ExtractFilesFromArchive (string.Format (guiStrings.MsgExtractingArchive, arc_name),
- arc, file_list, image_format);
+ m_main.SetStatusText (string.Format(guiStrings.MsgExtractingTo, m_arc_name, destination));
+ ExtractFilesFromArchive (string.Format (guiStrings.MsgExtractingArchive, m_arc_name), m_arc.Dir);
}
- private void ExtractFileFromArchive (EntryViewModel entry, string destination)
+ public void Extract (EntryViewModel entry, string destination)
{
- var view_model = ViewModel;
- var selected = CurrentDirectory.SelectedItems.Cast();
+ var view_model = m_main.ViewModel;
+ var selected = m_main.CurrentDirectory.SelectedItems.Cast();
IEnumerable file_list = view_model.GetFiles (selected);
if (!file_list.Any() && entry.Name == "..")
file_list = view_model.GetFiles (view_model);
if (!file_list.Any())
{
- SetStatusText (guiStrings.MsgChooseFiles);
+ m_main.SetStatusText (guiStrings.MsgChooseFiles);
return;
}
- string arc_name = Path.GetFileName (CurrentPath);
ExtractDialog extractDialog;
- if (file_list.Skip (1).Any())
- extractDialog = new ExtractArchiveDialog (arc_name, destination);
+ bool multiple_files = file_list.Skip (1).Any();
+ if (multiple_files)
+ extractDialog = new ExtractArchiveDialog (m_arc_name, destination);
else
extractDialog = new ExtractFile (entry, destination);
- extractDialog.Owner = this;
+ extractDialog.Owner = m_main;
var result = extractDialog.ShowDialog();
if (!result.Value)
return;
-
+ if (multiple_files)
+ {
+ m_skip_images = !Settings.Default.appExtractImages;
+ m_skip_script = !Settings.Default.appExtractText;
+ m_skip_audio = !Settings.Default.appExtractAudio;
+ }
destination = extractDialog.Destination;
if (!string.IsNullOrEmpty (destination))
{
destination = Path.GetFullPath (destination);
- Directory.CreateDirectory (destination);
- Directory.SetCurrentDirectory (destination);
+ PrepareDestination (destination);
}
- ImageFormat format = FormatCatalog.Instance.ImageFormats.FirstOrDefault (f => f.Tag.Equals (Settings.Default.appImageFormat));
+ if (!m_skip_images)
+ m_image_format = FormatCatalog.Instance.ImageFormats.FirstOrDefault (f => f.Tag.Equals (Settings.Default.appImageFormat));
- ExtractFilesFromArchive (string.Format (guiStrings.MsgExtractingFile, arc_name),
- m_app.CurrentArchive, file_list, format);
+ ExtractFilesFromArchive (string.Format (guiStrings.MsgExtractingFile, m_arc_name), file_list);
}
- private void ExtractFilesFromArchive (string text, ArcFile arc, IEnumerable file_list,
- ImageFormat image_format = null)
+ private void ExtractFilesFromArchive (string text, IEnumerable file_list)
{
- file_list = file_list.OrderBy (e => e.Offset);
- var extractProgressDialog = new ProgressDialog ()
+ if (file_list.Skip (1).Any() // file_list.Count() > 1
+ && (m_skip_images || m_skip_script || m_skip_audio))
+ file_list = file_list.Where (f => !(m_skip_images && f.Type == "image") &&
+ !(m_skip_script && f.Type == "script") &&
+ !(m_skip_audio && f.Type == "audio"));
+ if (!file_list.Any())
+ {
+ m_main.SetStatusText (string.Format ("{1}: {0}", guiStrings.MsgNoFiles, m_arc_name));
+ return;
+ }
+ m_file_list = file_list.OrderBy (e => e.Offset);
+ m_progress_dialog = new ProgressDialog ()
{
WindowTitle = guiStrings.TextTitle,
Text = text,
Description = "",
MinimizeBox = true,
};
- if (!file_list.Skip (1).Any()) // 1 == file_list.Count()
+ if (!m_file_list.Skip (1).Any()) // 1 == m_file_list.Count()
{
- extractProgressDialog.Description = file_list.First().Name;
- extractProgressDialog.ProgressBarStyle = ProgressBarStyle.MarqueeProgressBar;
+ m_progress_dialog.Description = m_file_list.First().Name;
+ m_progress_dialog.ProgressBarStyle = ProgressBarStyle.MarqueeProgressBar;
}
- bool convert_audio = Settings.Default.appConvertAudio;
- int extract_count = 0;
- Exception pending_error = null;
- extractProgressDialog.DoWork += (s, e) =>
- {
- try
- {
- int total = file_list.Count();
- foreach (var entry in file_list)
- {
- if (extractProgressDialog.CancellationPending)
- break;
- if (total > 1)
- extractProgressDialog.ReportProgress (extract_count*100/total, null, entry.Name);
- if (null != image_format && entry.Type == "image")
- ExtractImage (arc, entry, image_format);
- else if (convert_audio && entry.Type == "audio")
- ExtractAudio (arc, entry);
- else
- arc.Extract (entry);
- ++extract_count;
- }
- }
- catch (Exception X)
- {
- pending_error = X;
- }
- };
- extractProgressDialog.RunWorkerCompleted += (s, e) => {
- extractProgressDialog.Dispose();
- this.Activate();
- if (!ViewModel.IsArchive)
- {
- arc.Dispose();
- Dispatcher.Invoke (RefreshView);
- }
- SetStatusText (Localization.Format ("MsgExtractedFiles", extract_count));
- if (null != pending_error)
- PopupError (pending_error.Message, guiStrings.MsgErrorExtracting);
- };
- extractProgressDialog.ShowDialog (this);
+ m_convert_audio = !m_skip_audio && Settings.Default.appConvertAudio;
+ m_extract_count = 0;
+ m_pending_error = null;
+ m_progress_dialog.DoWork += ExtractWorker;
+ m_progress_dialog.RunWorkerCompleted += OnExtractComplete;
+ m_progress_dialog.ShowDialog (m_main);
+ m_extract_in_progress = true;
}
+
+ void ExtractWorker (object sender, DoWorkEventArgs e)
+ {
+ try
+ {
+ int total = m_file_list.Count();
+ foreach (var entry in m_file_list)
+ {
+ if (m_progress_dialog.CancellationPending)
+ break;
+ if (total > 1)
+ m_progress_dialog.ReportProgress (m_extract_count*100/total, null, entry.Name);
+ if (null != m_image_format && entry.Type == "image")
+ ExtractImage (m_arc, entry, m_image_format);
+ else if (m_convert_audio && entry.Type == "audio")
+ ExtractAudio (m_arc, entry);
+ else
+ m_arc.Extract (entry);
+ ++m_extract_count;
+ }
+ }
+ catch (Exception X)
+ {
+ m_pending_error = X;
+ }
+ }
+
+ static void ExtractImage (ArcFile arc, Entry entry, ImageFormat target_format)
+ {
+ using (var file = arc.OpenEntry (entry))
+ {
+ string source_ext = Path.GetExtension (entry.Name).TrimStart ('.').ToLowerInvariant();
+ if (target_format.Extensions.Any (ext => ext == source_ext))
+ {
+ // source extension matches target image format, copy file as is
+ using (var output = arc.CreateFile (entry))
+ file.CopyTo (output);
+ return;
+ }
+ ImageData image = ImageFormat.Read (file);
+ if (null == image)
+ throw new InvalidFormatException (string.Format ("{1}: {0}", guiStrings.MsgUnableInterpret, entry.Name));
+ string target_ext = target_format.Extensions.First();
+ string outname = Path.ChangeExtension (entry.Name, target_ext);
+ Trace.WriteLine (string.Format ("{0} => {1}", entry.Name, outname), "ExtractImage");
+ using (var outfile = ArchiveFormat.CreateFile (outname))
+ {
+ target_format.Write (outfile, image);
+ }
+ }
+ }
+
+ static void ExtractAudio (ArcFile arc, Entry entry)
+ {
+ using (var file = arc.OpenEntry (entry))
+ using (var sound = AudioFormat.Read (file))
+ {
+ if (null == sound)
+ throw new InvalidFormatException (string.Format ("{1}: {0}", guiStrings.MsgUnableInterpret, entry.Name));
+ ConvertAudio (entry.Name, sound);
+ }
+ }
+
+ public static void ConvertAudio (string entry_name, SoundInput input)
+ {
+ string source_format = input.SourceFormat;
+ if (CommonAudioFormats.Contains (source_format))
+ {
+ string output_name = Path.ChangeExtension (entry_name, source_format);
+ using (var output = ArchiveFormat.CreateFile (output_name))
+ {
+ input.Source.Position = 0;
+ input.Source.CopyTo (output);
+ }
+ }
+ else
+ {
+ var wav_format = FormatCatalog.Instance.AudioFormats.Where (f => f.Tag == "WAV").First();
+ string output_name = Path.ChangeExtension (entry_name, "wav");
+ using (var output = ArchiveFormat.CreateFile (output_name))
+ wav_format.Write (input, output);
+ }
+ }
+
+ void OnExtractComplete (object sender, RunWorkerCompletedEventArgs e)
+ {
+ m_extract_in_progress = false;
+ m_progress_dialog.Dispose();
+ m_main.Activate();
+ if (!m_main.ViewModel.IsArchive)
+ {
+ m_main.Dispatcher.Invoke (m_main.RefreshView);
+ }
+ m_main.SetStatusText (Localization.Format ("MsgExtractedFiles", m_extract_count));
+ if (null != m_pending_error)
+ {
+ if (m_pending_error is OperationCanceledException)
+ m_main.SetStatusText (m_pending_error.Message);
+ else
+ m_main.PopupError (m_pending_error.Message, guiStrings.MsgErrorExtracting);
+ }
+ this.Dispose();
+ }
+
+ #region IDisposable Members
+ bool disposed = false;
+
+ public void Dispose ()
+ {
+ if (!m_extract_in_progress)
+ {
+ if (!disposed)
+ {
+ if (m_should_dispose)
+ m_arc.Dispose();
+ disposed = true;
+ }
+ GC.SuppressFinalize (this);
+ }
+ }
+
+ ~GarExtract ()
+ {
+ Dispose();
+ }
+ #endregion
}
}
diff --git a/ImagePreview.cs b/ImagePreview.cs
index 254856bc..ad8b681b 100644
--- a/ImagePreview.cs
+++ b/ImagePreview.cs
@@ -313,30 +313,5 @@ namespace GARbro.GUI
}, DispatcherPriority.ContextIdle);
}
}
-
- void ExtractImage (ArcFile arc, Entry entry, ImageFormat target_format)
- {
- using (var file = arc.OpenEntry (entry))
- {
- string source_ext = Path.GetExtension (entry.Name).TrimStart ('.').ToLowerInvariant();
- if (target_format.Extensions.Any (ext => ext == source_ext))
- {
- // source extension matches target image format, copy file as is
- using (var output = arc.CreateFile (entry))
- file.CopyTo (output);
- return;
- }
- ImageData image = ImageFormat.Read (file);
- if (null == image)
- throw new InvalidFormatException (string.Format ("{1}: {0}", guiStrings.MsgUnableInterpret, entry.Name));
- string target_ext = target_format.Extensions.First();
- string outname = Path.ChangeExtension (entry.Name, target_ext);
- Trace.WriteLine (string.Format ("{0} => {1}", entry.Name, outname), "ExtractImage");
- using (var outfile = ArchiveFormat.CreateFile (outname))
- {
- target_format.Write (outfile, image);
- }
- }
- }
}
}
diff --git a/MainWindow.xaml.cs b/MainWindow.xaml.cs
index cd6dffea..db45b4b7 100644
--- a/MainWindow.xaml.cs
+++ b/MainWindow.xaml.cs
@@ -210,7 +210,7 @@ namespace GARbro.GUI
/// Set data context of the ListView.
///
- private DirectoryViewModel ViewModel
+ public DirectoryViewModel ViewModel
{
get
{
@@ -219,7 +219,7 @@ namespace GARbro.GUI
return null;
return source.SourceCollection as DirectoryViewModel;
}
- set
+ private set
{
StopWatchDirectoryChanges();
var cvs = this.Resources["ListViewSource"] as CollectionViewSource;
diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs
index af9fd641..bf9aea99 100644
--- a/Properties/AssemblyInfo.cs
+++ b/Properties/AssemblyInfo.cs
@@ -51,5 +51,5 @@ using System.Windows;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion ("1.1.1.17")]
-[assembly: AssemblyFileVersion ("1.1.1.17")]
+[assembly: AssemblyVersion ("1.1.1.18")]
+[assembly: AssemblyFileVersion ("1.1.1.18")]