Archive

Archive for May, 2009

When more On becomes Off

May 31, 2009 1 comment

The other day, after a conversation with Amanda, I had a little thought. If one is on the rooftop and one begins sliding, one is sliding on the roof. If one continues to slide on the roof one will end up sliding off the roof. ‘On’ and ‘off’ are supposed to be opposites. But here is an example of one thing continuing becomes the opposite of what it is.

So curious.

Categories: Uncategorized

Laymen have lost the ability to record

May 21, 2009 Leave a comment

If you wanted to record audio, how do you do it? Twenty years ago the answer was easy. Every tape player had the ability to record, had a microphone and an in line. The recording industry thought it would be the end of music. Then the CD player came along. True, most devices had both tape and CD, but more and more didn’t have tape. It was becoming okay to have music devices that didn’t record because there were still tape players around.

Then Apple came out with the iPod. In a desire to simply they didn’t include recording functionality. Now practically all competing music players don’t have the ability to record. My Creative Zen had a microphone and could record radio. My current Walkman can’t record. So if I had to record something I wouldn’t know how to do it. I know my phone can record, but I don’t think the quality is that good, and I have to have the phone up to my head. I’ve felt like we’ve lost the ability to record. The music industry got their wish.

Yes, if someone wanted to record something they could purchase devices to do it and wire things up. It’s still possible to do. Most likely someone would record from a microphone to a laptop. But the ease at which we used to record audio is gone.

Categories: Uncategorized

Speaking Jaredeese

May 19, 2009 Leave a comment

For the last two years the stuff I’ve worked on has not been public knowledge. The Beta for Exchange 2010 has recently become public and as a result there have been official documents about it. For all those who would like to know what I work on, there is an excellent video posted by Scott Schnoll http://msexchangeteam.com/archive/2009/05/18/451353.aspx. It’s five minutes long and Scott was able to explain what happens in a manner that I find easy to understand.

Categories: Uncategorized

I’m allergic to dogs (kind of)

May 11, 2009 4 comments

I went to see the allergist today to talk about my mysterious hives and told him that my current suspicion is sodium bisulphate. He said that there is no test for allergies to meta sulfates, but while I was there he’d run standard skin tests. Turns out I’m mildly allergic to dogs. Who knew!

So the allergist is going to have my experiment on myself to find out if I can prove I am allergic to sodium bisulphate. He doesn’t think I can do it because it’s very hard to actually methodically prove. Here’s to the scientific method.

Categories: Uncategorized

Programmatically setting the metadata title of an image file

May 10, 2009 Leave a comment

So different applications I use (think Windows Live Skydrive) don’t make the name of a file predominant, but they do have features around the title of the picture file. I find this odd because I put effort into naming the file, but not into the title. Why would a picture have a different title from file name?! Okay, maybe if you had the same picture with different resolutions that could happen, but that’s the only thing I can think of. Either way I want a programmatic way to set the title to the file name. I thought a PowerShell script would be able to do it, but Windows seem to have gone out of it’s way to make modifying picture metadata difficult. So I spent way more time on this than I thought I would but I’m proud of my results. Here’s the C# code should anyone want the same.

using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.Remoting.Messaging;
using System.Threading;
using System.Windows.Media.Imaging;

namespace TitleSetter
{
    /// <summary>
    /// Class for setting the title of an image if one does not already exist
    /// </summary>
    /// <author>jader3rd</author>
    public class TitleSetter
    {
        private readonly String dir, pat;
        private int outStandingTasks, filesDetermined, totalFiles;
        ManualResetEvent tasksComplete;

        static int Main(string[] args)
        {
            int returnee = 0;
            try
            {
                if (2 == args.Length)
                {
                    TitleSetter ts = new TitleSetter(args[0], args[1]);
                    ts.Output = Console.Out;
                    ts.setTitles();
                }
                else
                {
                    Console.WriteLine("Usage:{0} <Directory Path> <File Pattern>", Process.GetCurrentProcess().ProcessName);
                }
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(ex.ToString());
                returnee = ex.GetHashCode();
            }

            return returnee;
        }

        /// <summary>
        /// Initialize the Title Setter object
        /// </summary>
        /// <param name="directory">The directory to scan for pictures</param>
        /// <param name="pattern">The pattern of the file name to look for pictures for</param>
        public TitleSetter(String directory, String pattern)
        {
            dir = directory;
            pat = pattern;
            tasksComplete = new ManualResetEvent(false);
        }

        /// <summary>
        /// The stream to send output to
        /// </summary>
        public TextWriter Output { get; set; }

        /// <summary>
        /// This process was supposed to be way more asynchronous file I/O friendly, but I couldn't find a way
        /// to get the BitmapFrame class to go to a byte array. As a result I couldn't do async I/O. So this 
        /// delegate is needed. Of course this now means that async calls are doing synchronous I/O, which is 
        /// a sin, but I thought it would be more efficient none the less.
        /// </summary>
        /// <param name="file"></param>
        delegate void FileAction(FileInfo file);

        /// <summary>
        /// Go through all of the files found in the directory that match the pattern and set
        /// the picture title
        /// </summary>
        public void setTitles()
        {
            tasksComplete.Reset();
            outStandingTasks = 0;
            filesDetermined = 0;
            FileAction fa = new FileAction(setTitle);

            String[] fileNames = Directory.GetFiles(dir, pat);
            totalFiles = fileNames.Length;

            if (700 < totalFiles)
            {
                writeOutput("Warning: There may be performance issues with more than 700 files");
            }

            foreach (String fileName in fileNames)
            {
                FileInfo file = new FileInfo(fileName);
                fa.BeginInvoke(file, endSetTitle, file);
                Interlocked.Increment(ref outStandingTasks);
            }

            fileNames = null;
            if (0 == outStandingTasks)
            {
                tasksComplete.Set();
            }
            
            tasksComplete.WaitOne();
        }

        /// <summary>
        /// Set the title for an individual file
        /// </summary>
        /// <param name="file">The file to set the title for</param>
        private void setTitle(FileInfo file)
        {
            if (String.IsNullOrEmpty(Thread.CurrentThread.Name))
            {
                Thread.CurrentThread.Name = file.Name;
            }
            using (FileStream stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            {
                BitmapFrame frame = BitmapFrame.Create(stream);
                InPlaceBitmapMetadataWriter bitmeta = frame.CreateInPlaceBitmapMetadataWriter();
                String originalTitle = bitmeta.Title;
                if (String.IsNullOrEmpty(originalTitle))
                {
                    if (bitmeta.TrySave())
                    {
                        writeOutput("%{0,-3} {1}", (100 * Interlocked.Increment(ref filesDetermined)) / totalFiles, file.Name);
                        bitmeta.Title = Path.GetFileNameWithoutExtension(file.Name);
                        // I don't know why this TrySave is needed, but it won't save without it.
                        bitmeta.TrySave();
                    }
                    else
                    {
                        Interlocked.Increment(ref filesDetermined);
                        throw new IOException("Unable to change title for " + file.Name);
                    }
                }
                else
                {
                    writeOutput("%{0,-3} {1} is already set to \"{2}\"", (100 * Interlocked.Increment(ref filesDetermined)) / totalFiles, file.Name, originalTitle);
                }
                stream.Close();
            }
        }

        /// <summary>
        /// Write output to the given output stream
        /// </summary>
        /// <param name="format">The message</param>
        /// <param name="arguments">message arguments</param>
        private void writeOutput(String format, params Object[] arguments)
        {
            if (null != Output)
            {
                Output.WriteLine(format, arguments);
            }
        }

        /// <summary>
        /// Finishes the action of setting the title
        /// </summary>
        /// <param name="result">The result from the setTitle call</param>
        private void endSetTitle(IAsyncResult result)
        {
            FileInfo file = result.AsyncState as FileInfo;
            try
            {
                FileAction fa = (FileAction)((AsyncResult)result).AsyncDelegate;
                fa.EndInvoke(result);

            }
            catch (Exception ex)
            {
                writeOutput("Exception caught for file {0}{1}{2}", file.Name, Environment.NewLine, ex);
            }

            Interlocked.Decrement(ref outStandingTasks);
            if (0 == outStandingTasks)
            {
                tasksComplete.Set();
            }
        }
    }
}
Categories: Uncategorized