Example #1
0
        public CacheView(ImageCache cache)
        {
            this.cache = cache;

            InitializeComponent();
            this.Icon = Properties.Resources.Icon1;

            this.entryInfoBindingSource.DataSource = new BindingSource(this.entries, null);

            this.toolStripButtonEnableSwap.Checked         = Program.EnableSwap;
            this.toolStripButtonEnableSwap.CheckedChanged += ToolStripButtonEnableSwap_CheckedChanged;
        }
Example #2
0
        public static void Main(string[] args)
        {
            try
            {
                if ((args.Length >= 1) && String.Equals(args[0], "-waitdebugger"))
                {
                    while (!Debugger.IsAttached)
                    {
                        Thread.Sleep(250);
                    }
                    ShiftArgs(ref args, 1);
                }

                if ((args.Length == 2) && String.Equals(args[0], "-server"))
                {
                    Environment.ExitCode = ImageServer.RunServer(args[1]);
                    return;
                }


                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);


                bool showLogOnStart = false;
                while (args.Length >= 1)
                {
                    switch (args[0])
                    {
                    default:
                        goto Break;

                    case "-profile":
                        ProfileMode = true;
                        ShiftArgs(ref args, 1);
                        break;

                    case "-showlog":
                        showLogOnStart = true;
                        ShiftArgs(ref args, 1);
                        break;

                    case "-swap":
                        EnableSwap = true;
                        ShiftArgs(ref args, 1);
                        break;

                    case "-noswap":
                        EnableSwap = false;
                        ShiftArgs(ref args, 1);
                        break;
                    }
                }
Break:

                if (args.Length == 0)
                {
                    // HACK: based on what WinMerge does - usability is suspect but still much better than FolderBrowserDialog.
                    // See: http://www.codeproject.com/Articles/44914/Select-file-or-folder-from-the-same-dialog
                    using (OpenFileDialog dialog = new OpenFileDialog())
                    {
                        dialog.ValidateNames   = false;
                        dialog.CheckFileExists = false;
                        dialog.CheckPathExists = false;
                        dialog.Title           = "Select a Folder";
                        dialog.FileName        = "Select Folder.";
                        if (dialog.ShowDialog() != DialogResult.OK)
                        {
                            return;
                        }
                        args = new string[] { Path.GetDirectoryName(dialog.FileName) };
                    }
                }

                if (args.Length != 1)
                {
                    MessageBox.Show("Program must take one argument which is the path to a directory containing images to adjust.");
                    return;
                }

                Window     window;
                ImageCache cache = new ImageCache();

                string directory     = Path.GetFullPath(args[0]);
                string scanDirectory = GetScanDirectoryFromTargetDirectory(directory);

                if (!Directory.Exists(directory))
                {
                    MessageBox.Show(String.Format("Specified directory does not exist: \"{0}\"", directory));
                    return;
                }

                XmlDocument settings = new XmlDocument();
                {
                    string settingsPath = Path.Combine(scanDirectory, SettingsFile);
                    if (File.Exists(settingsPath))
                    {
                        settings.Load(settingsPath);
                    }
                }

                GlobalOptions options = new GlobalOptions(settings.CreateNavigator().SelectSingleNode("/*/options"));
                {
                    using (GlobalOptionsDialog dialog = new GlobalOptionsDialog(options, directory))
                    {
                        Application.Run(dialog);
                        if (dialog.DialogResult != DialogResult.OK)
                        {
                            return;
                        }
                    }
                }

                if (showLogOnStart)
                {
                    logWindow = new LoggingWindow();
                    logWindow.Show();
                }

                // scan items
                List <Item> items = new List <Item>();
                foreach (string filePath in Directory.GetFiles(scanDirectory))
                {
                    string fileName = Path.GetFileName(filePath);
                    if (String.Equals(fileName, SettingsFile, StringComparison.OrdinalIgnoreCase))
                    {
                        continue;
                    }

                    bool extUpper = String.Equals(Path.GetExtension(fileName), Path.GetExtension(fileName).ToUpper());
                    //fileName = Path.ChangeExtension(fileName, extUpper ? ".JPG" : ".jpg");

                    Item item = new Item(Path.Combine(directory, fileName), options, cache);
                    items.Add(item);

                    XPathNavigator itemNav = settings.CreateNavigator().SelectSingleNode(String.Format("/*/items/item[file=\"{0}\"]", fileName));
                    if (itemNav != null)
                    {
                        item.ReadXml(itemNav);
                    }
                }

                window = new Window(directory, items, cache, options);
                window.Show();

                window.LastAnalysisTask = BatchAnalyzerQueue.BeginAnalyzeBatch(items);


                Application.Run(window);


                LoggingWindow logw = logWindow;
                if (logw != null)
                {
                    logw.Close();
                }

                window.LastAnalysisTask.Wait(); // allow any unfinished actions to cancel and dispose state

                cache.Dispose();
                SerializationManager.Manager.Dispose();
                ImageClient.Close();
            }
            catch (Exception exception)
            {
                Debugger.Log(0, null, exception.ToString());
                MessageBox.Show(exception.ToString());
            }
        }
Example #3
0
        public void StartSwapOut(ImageCache cache)
        {
            lock (this)
            {
                Debug.Assert(Program.EnableSwap);

                if (this.outTask != null)
                {
                    return;
                }
                if (this.holders.Count != 0)
                {
                    return;
                }

                Stopwatch elapsed = Stopwatch.StartNew();

#if true // TODO: remove hack
                EventWaitHandle swapOutDelay = new EventWaitHandle(false, EventResetMode.AutoReset);
#endif
                Task <bool> serializationTask = null;

                Task <ManagedBitmap> oldBitmap = this.bitmap;

                // 'this' is not locked at the time 'cache' is used below in the task delegates

                this.outTask = new Task <bool>(
                    delegate()
                {
                    Profile profile = new Profile("SwapOut {0}", this.id);

#if true // TODO: remove hack
                    profile.Push("Hack delay for swapins");
                    // HACK: wait a little to allow swapins to start before swapouts
                    EventWaitHandle localSwapOutDelay = Interlocked.Exchange(ref swapOutDelay, null);
                    if (localSwapOutDelay != null)     // race: swapin can grab and clear this before we get here
                    {
                        localSwapOutDelay.WaitOne(100);
                    }
                    profile.Pop();
                    //
#endif
                    profile.Push("WaitSwapOutGate");
                    cache.WaitSwapOutGate();     // defer to in-flight swapins
                    profile.Pop();

                    lock (this)
                    {
                        Debug.Assert(this.swapFilePath == null);
                        Debug.Assert(this.swapFileStream == null);
                        this.swapFilePath   = Path.GetTempFileName();
                        this.swapFileStream = new FileStream(this.swapFilePath, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite, 4096, FileOptions.DeleteOnClose);
                    }

                    profile.Push("oldBitmap.Wait()");
                    oldBitmap.Wait();     // wait for an old in-flight creation to complete
                    profile.Pop();

                    profile.Push("Serialize");
                    serializationTask = new Task <bool>(
                        delegate()
                    {
                        SetIOPriority(this.swapFileStream, PRIORITY_HINT.IoPriorityHintLow);
                        ManagedBitmap.Serialize(this.swapFileStream, oldBitmap.Result);
                        SetIOPriority(this.swapFileStream, PRIORITY_HINT.IoPriorityHintNormal);
                        return(false);
                    });
                    SerializationManager.Manager.EnqueueWriteTask(serializationTask);
                    serializationTask.Wait();
                    profile.Pop();

                    profile.Push("Enqueue oldBitmap");
                    lock (this)
                    {
                        this.oldBitmaps.Add(oldBitmap.Result);     // remove current bitmap and enqueue for destruction upon zero refs
                    }
                    profile.Pop();

                    profile.Push("Epilog");
                    cache.Trace("swapout", this, elapsed);
                    cache.PurgeDisposeList();
                    profile.Pop();

                    profile.End();
                    //Program.Log(LogCat.Perf, profile.ToString());

                    return(false);
                });

                this.bitmap = new Task <ManagedBitmap>(
                    delegate()
                {
                    Profile profile = new Profile("SwapIn {0}", this.id);

                    profile.Push("outTask.Wait()");
#if true // TODO: remove hack
                    // HACK: release delay immediately if swapin is requested
                    EventWaitHandle localSwapOutDelay = Interlocked.Exchange(ref swapOutDelay, null);
                    if (localSwapOutDelay != null)
                    {
                        localSwapOutDelay.Set();
                    }
                    //
#endif
                    SerializationManager.Manager.Prioritize(serializationTask);
                    Debug.Assert(this.outTask != null);
                    this.outTask.Wait();     // ensure in-progress swapout finishes
                    profile.Pop();

                    profile.Push("cache.BeginSwapIn()");
                    cache.BeginSwapIn();
                    profile.Pop();
                    try
                    {
                        Stopwatch elapsed2 = Stopwatch.StartNew();

                        Debug.Assert(this.swapFilePath != null);
                        Debug.Assert(this.swapFileStream != null);

                        profile.Push("Deserialize");
                        ManagedBitmap bitmap            = null;
                        Task <bool> deserializationTask = new Task <bool>(
                            delegate()
                        {
                            bitmap = ManagedBitmap.Deserialize(this.swapFileStream);
                            return(false);
                        });
                        SerializationManager.Manager.EnqueueReadTask(deserializationTask);
                        deserializationTask.Wait();
                        this.swapFilePath          = null;
                        Stream localSwapFileStream = this.swapFileStream;
                        this.swapFileStream        = null;
                        localSwapFileStream.Dispose();
                        this.outTask = null;
                        profile.Pop();

                        profile.Push("Epilog");
                        cache.Trace("swapin", this, elapsed2);
                        cache.PurgeDisposeList();

                        StartBitmapCompleteWaiter();

                        return(bitmap);
                    }
                    finally
                    {
                        cache.EndSwapIn();
#if true // TODO: remove hack
                        if (localSwapOutDelay != null)
                        {
                            localSwapOutDelay.Dispose();
                        }
#endif
                        profile.Pop();     // Epilog - here to include cache.EndSwapIn()

                        profile.End();
                        //Program.Log(LogCat.Perf, profile.ToString());
                    }
                });

                this.outTask.Start();
            }
        }
Example #4
0
        public static void Main(string[] args)
        {
            try
            {
                if ((args.Length >= 1) && String.Equals(args[0], "-waitdebugger"))
                {
                    while (!Debugger.IsAttached)
                    {
                        Thread.Sleep(250);
                    }
                    ShiftArgs(ref args, 1);
                }

                if ((args.Length == 2) && String.Equals(args[0], "-server"))
                {
                    Environment.ExitCode = ImageServer.RunServer(args[1]);
                    return;
                }


                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);


                bool showLogOnStart = false;
                while (args.Length >= 1)
                {
                    switch (args[0])
                    {
                    default:
                        goto Break;

                    case "-profile":
                        ProfileMode = true;
                        ShiftArgs(ref args, 1);
                        break;

                    case "-showlog":
                        showLogOnStart = true;
                        ShiftArgs(ref args, 1);
                        break;

                    case "-swap":
                        EnableSwap = true;
                        ShiftArgs(ref args, 1);
                        break;

                    case "-noswap":
                        EnableSwap = false;
                        ShiftArgs(ref args, 1);
                        break;
                    }
                }
Break:

                if (args.Length == 0)
                {
                    // HACK: based on what WinMerge does - usability is suspect but still much better than FolderBrowserDialog.
                    // See: http://www.codeproject.com/Articles/44914/Select-file-or-folder-from-the-same-dialog
                    using (OpenFileDialog dialog = new OpenFileDialog())
                    {
                        dialog.ValidateNames   = false;
                        dialog.CheckFileExists = false;
                        dialog.CheckPathExists = false;
                        dialog.Title           = "Select a Folder";
                        dialog.FileName        = "Select Folder.";
                        if (dialog.ShowDialog() != DialogResult.OK)
                        {
                            return;
                        }
                        args = new string[] { Path.GetDirectoryName(dialog.FileName) };
                    }
                }

                if (args.Length != 1)
                {
                    MessageBox.Show("Program must take one argument which is the path to a directory containing images to adjust.");
                    return;
                }

                Window     window = null;
                ImageCache cache  = new ImageCache();

                string directory     = Path.GetFullPath(args[0]);
                string scanDirectory = GetScanDirectoryFromTargetDirectory(directory);

                if (!Directory.Exists(directory))
                {
                    MessageBox.Show(String.Format("Specified directory does not exist: \"{0}\"", directory));
                    return;
                }

                // load xml file
                XPathNavigator settingsNav;
                {
                    XmlDocument settings     = new XmlDocument();
                    string      settingsPath = Path.Combine(scanDirectory, SettingsFile);
                    if (File.Exists(settingsPath))
                    {
                        settings.Load(settingsPath);
                    }
                    settingsNav = settings.CreateNavigator();
                }

                GlobalOptions options = new GlobalOptions(settingsNav.SelectSingleNode("/*/options"));
                {
                    using (GlobalOptionsDialog dialog = new GlobalOptionsDialog(options, directory))
                    {
                        Application.Run(dialog);
                        if (dialog.DialogResult != DialogResult.OK)
                        {
                            return;
                        }
                    }
                }

                if (showLogOnStart)
                {
                    logWindow = new LoggingWindow();
                    logWindow.Show();
                }

                // read saved items from xml
                List <Item> items = new List <Item>();
                Dictionary <string, bool> filesWithItems = new Dictionary <string, bool>();
                foreach (XPathNavigator itemNav in settingsNav.Select("/*/items/item"))
                {
                    string fileName = itemNav.SelectSingleNode("file").Value;
                    string filePath = Path.Combine(directory, fileName);
                    if (File.Exists(filePath)) // drop item records for which file no longer exists
                    {
                        Item item = new Item(Path.Combine(directory, fileName), options, cache);
                        item.ReadXml(itemNav);

                        items.Add(item);

                        filesWithItems[fileName.ToLowerInvariant()] = false;
                    }
                }

                // add new records for any files that don't have a record
                foreach (string filePath in Directory.GetFiles(scanDirectory))
                {
                    string fileName = Path.GetFileName(filePath);
                    if (String.Equals(fileName, SettingsFile, StringComparison.OrdinalIgnoreCase))
                    {
                        continue;
                    }

                    if (!filesWithItems.ContainsKey(fileName.ToLowerInvariant()))
                    {
                        Item item = new Item(Path.Combine(directory, fileName), options, cache);
                        items.Add(item);

                        item.SettingsNav = settingsNav; // no match; try after hash has been computed
                    }
                }

                // timestamp actions
                if (options.Timestamps.HasValue)
                {
                    Parallel.ForEach(
                        items,
                        GetProcessorConstrainedParallelOptions2(CancellationToken.None),
                        delegate(Item item)
                    {
                        if (options.Timestamps.Value)
                        {
                            if (!options.TimestampsOverwriteExisting)
                            {
                                DateTime existingTimestamp;
                                if (TryParseFilenameTimestamp(Path.GetFileName(item.TargetPath), out existingTimestamp))
                                {
                                    return;
                                }
                            }

                            DateTime fsCreated, fsModified, exifCreated;
                            bool found = TryGetTimestamps(
                                item.SourcePath,
                                out fsCreated,
                                out fsModified,
                                out exifCreated);

                            string created  = fsCreated.ToString("s").Replace("T", ".");
                            string modified = fsModified.ToString("s").Replace("T", ".");
                            string exif     = found ? exifCreated.ToString("s").Replace("T", ".") : "<no data>";

                            string newName = StripFilenameTimestamp(Path.GetFileName(item.TargetPath));
                            string text    = FormatFilenameTimestamp(
                                found
                                        ? exifCreated
                                        : (!options.TimestampsExifMissingModifiedInsteadOfCreated ? fsCreated : fsModified));
                            newName = String.Concat(text, " ", newName);

                            item.RenamedFileName = newName;
                        }
                        else
                        {
                            item.RenamedFileName = StripFilenameTimestamp(Path.GetFileName(item.TargetPath));
                        }
                    });

                    // ensure no duplicate names
                    Dictionary <string, bool> usedName = new Dictionary <string, bool>();
                    foreach (Item item in items)
                    {
                        if (usedName.ContainsKey(item.RenamedFileName))
                        {
                            int suffix = 0;
                            while (true)
                            {
                                string newName = String.Concat(Path.GetFileNameWithoutExtension(item.RenamedFileName), "-", ++suffix, Path.GetExtension(item.RenamedFileName));
                                if (!usedName.ContainsKey(newName))
                                {
                                    item.RenamedFileName = newName;
                                    break;
                                }
                            }
                        }
                        usedName.Add(item.RenamedFileName, false);
                    }
                }

                if (items.Count != 0)
                {
                    window = new Window(directory, items, cache, options);
                    window.Show();

                    window.LastAnalysisTask = BatchAnalyzerQueue.BeginAnalyzeBatch(items);

                    Application.Run(window);
                }
                else
                {
                    MessageBox.Show(String.Format("The specified folder \"{0}\" contains no images.", scanDirectory));
                }

                LoggingWindow logw = logWindow;
                if (logw != null)
                {
                    logw.Close();
                }

                if (window != null)
                {
                    window.LastAnalysisTask.Wait(); // allow any unfinished actions to cancel and dispose state
                }

                cache.Dispose();
                SerializationManager.Manager.Dispose();
                ImageClient.Close();
            }
            catch (Exception exception)
            {
                Debugger.Log(0, null, exception.ToString());
                MessageBox.Show(exception.ToString());
            }
        }