Corel VideoStudio Pro and QuickTime, a Workaround

I really like Corel VideoStudio Pro for video editing, and I’ve been using it for 4 years now.  Unfortunately it really falls down when it comes to QuickTime videos.  Now that I own a Canon 7D that records in QuickTime format, this is a problem.

The underlying issue is that the software seems to lose all knowledge of its QuickTime capabilities when QuickTime has been upgraded on the machine.  Since I use iTunes on this computer for my iPhone and iPad, there’s no possibility for me to downgrade QuickTime for VideoStudio.

So tonight I set out to find a solution.

QuickTime Pro and some C#

I purchased QuickTime Pro ($30) and found that I could take a .mov file and perform a Pass Through MP4 conversion which essentially just strips the embedded mp4 data from the .mov file without doing any real transcoding.  This is exactly what I want – I don’t want to lose any video quality just because I want the raw mp4.

The problem now is that this is a completely manual process that I would need to do on each and every video file.  File -> Export -> MPEG-4 -> Pass Through -> blah blah.

There’s just no way that was going to work, so I decided to write some code against the QuickTime COM api to automate the process.

The following code is for a command-line executable that will do this mov to mp4 conversion to a batch of mov files:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
using System;
using System.IO;
using System.Reflection;
using System.Threading;
using QTOControlLib;
using QTOLibrary;
using QuickTimePlayerLib;
 
namespace QTExtractor
{
    class Program
    {
        static void Main(string[] args)
        {
            // get the player, and the "control"
            QuickTimePlayerApp qtApp = new QuickTimePlayerApp();
 
            // have to wait for QT to open up.
            Thread.Sleep(5000);
 
            // get a Player instance
            QuickTimePlayer qtPlayer = qtApp.Players[1];
 
            // the exporter we will configure once and re-use
            QTExporter exporter = null;
            foreach (string movFile in args)
            {
                // open the movie
                qtPlayer.OpenURL(movFile);
 
                // get the QTControl
                QTControl control = qtPlayer.QTControl;
 
                // configure the exporter
                if (exporter == null)
                {
                    if (control.QuickTime.Exporters.Count == 0)
                    {
                        control.QuickTime.Exporters.Add();
                    }
 
                    exporter = control.QuickTime.Exporters[1];
                    exporter.TypeName = "MPEG-4";
                    exporter.ShowProgressDialog = true;
 
                    // load our embedded settings
                    string settingsXml = "";
                    using (Stream resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("QTExtractor.Settings.Settings.xml"))
                    {
                        if (resourceStream == null)
                        {
                            throw new InvalidOperationException("Unable to locate the embedded settings.xml file for use with QuickTime Pro.");
                        }
 
                        using (StreamReader reader = new StreamReader(resourceStream))
                        {
                            settingsXml = reader.ReadToEnd();
                        }
                    }
 
                    // set the settings xml
                    CFObject newSettings = new CFObject();
                    newSettings.XML = settingsXml;
                    exporter.Settings = newSettings;
                }
 
                // set the datasource to the new movie
                exporter.SetDataSource(control.Movie);
 
                // uncomment to obtain new settings xml for use in exports
                //exporter.ShowSettingsDialog();
                //string settings = exporter.Settings.XML;
                //File.WriteAllText(@"C:\temp\settings.xml", settings);
 
                // just place the mp4 alongside the mov
                string targetFile = Path.Combine(Path.GetDirectoryName(movFile), Path.GetFileNameWithoutExtension(movFile) + ".mp4");
                exporter.DestinationFileName = targetFile;
 
                // Go!
                exporter.BeginExport();
            }
 
            // close the player
            qtPlayer.Close();
        }
    }
}

After building this, I added a shortcut to my Windows 7 SendTo folder.

Now, in my video folder I’m able to multi-select as many .mov files as necessary, righ-click and select Send To -> QTExtractor.  An .mp4 file will be created for each .mov!

The only downside is that the QT UI pops up as it is working – I haven’t looked but I suspect I can’t get around this.  Oh well, this should suffice until Corel gets their act together.

iPhone Objective-C for the C# Developer

If you’re a C# developer making your first foray into the land of iPhone and Objective-C programming, you probably have a question or two.  I recently started working in earnest on an iPhone app, so I figured I would write down some of the tips I’ve picked up thus far.

Here they are in no particular order.  No particular level importance.  Just some things that I had to learn and which may help you as well.

Objective-C

  • It’s a strict super-set of C, so straight C code is compilable in Objective-C
  • Back to the old header and implementation files (.h and .m, respectively)
  • There are two types of methods in classes, instance and class methods.  Denoted by a prepended “+” or “-” on the method prototype.  Class methods are just like static.
  • All methods are public(!).  That’s right, read that again.  There’s a hack/technique having to do with Objective-C categories to help hide them in the IDE, but they are still callable.
  • NSObject is System.Object.
  • No garbage collection on the iPhone, there is  reference counting instead.  More on this later.
  • What we typically think of as constructors are “init” methods.  Destructors are “dealloc”.  There’s nothing special about these methods, it’s just convention.
  • Properties are denoted with @property lines in the header file.  Corresponding @synthesize statements in the implementation file generate the property code.  Special directives in the @property declaration determine the specifics of the implementation (nonatomic, retain, etc.).
  • Use #import over #include – it prevents a file from being indrectly #included more than once.
  • What .Net calls Interfaces are called Protocols in Objective-C.
  • this pointer is called self
  • base is super
  • Methods are referred to as selectors.  Calling a method is referred to as sending a message to an object.
  • Message sending syntax is [recipient method] or [recipient method:paramvalue] or [recipient method:paramValue param2name:param2value]
  • @selector() is for specifying what are essentially delegates.
  • id datatype is basically NSObject*
  • There are C strings and there are NSStrings.  C string constants are defined like “something”, NSString constants are defined like @”something”
  • [[someClass alloc] init] is the typical instantiation pattern. Sometimes there are parameters, as in [[someClass alloc] initWithValue:someValue].   Sometimes you can just call a factory method on the class as in [someClass someClassFromData:data].  The only real difference has to do with the reference counting of the returned object (again, by convention).
  • Events are achieved by what they call delegation – registering/attaching an object that adheres to a protocol (interface) to subscribe to events (called Actions).
  • No namespaces, but there are categories which I haven’t bothered touching.

Reference Counting

  • NSObject implements reference counting.
  • Calling alloc or copy sets the reference count to 1.
  • To decrement the reference count, call release.
  • When the reference count hits 0, NSObject calls dealloc.  NEVER call dealloc yourself.
  • Call retain to increment the ref count.  Basically, if you need to keep hold of an object for longer than the duration of one message event cycle (event handler), call retain.    You don’t need to call retain on an object that you directly created with an alloc or copy call – NSObject called retain for you.
  • Calling release one too many times is bad – dealloc will end up getting called twice and cause a crash. 
  • There is an AutoReleasePool and the ability to call autorelease on NSObject.
  • When you call autorelease, the release  call gets posponed/scheduled in the AutoReleasePool.  This is used when a function needs to return a newly created object to the caller.  If it doesn’t call release, the ref count will be incorrect.  If it does call release, it will immediately be deallocated.    Calling autorelease will give the caller time to call retain to take ownership.
  • When does the autoreleasepool finally call release?  The pool gets drained at the end of every message pump loop, cleaning up any autoreleased objects.
  • So, so summarize… if you call alloc or copy, you need to call release.  If you use a class factory method and need to keep the object around, call retain and be sure to have a matching release later.

Interface Builder

  • I have yet to see why Apple developers fall all over themselves about Interface Builder.  No comparison to Visual Studio.
  • Interface Builder writes to .xib files (which for some unknown reason are called Nib files).
  • It parses your header files for IBAction and IBOutlet on declarations to determine event handlers and variables for interface elements respectively.
  • IBAction is a #define for void.
  • IBOutlet is a #define for blank.
  • Just saving the .h file is sufficient for IB to reparse and pickup the changes.

Ok, I’m tired of typing now.  That ended up a little longer than I intended but I hope it helps you to get up to speed.

More PowerShell – a Cmdlet

This past weekend I spent some time reading up on and writing my first PowerShell cmdlet.   The cmdlet is an easy one, but replaces a PS function I have copy/pasted into several scripts here and there to handle cleaning out directories of old backups or other types of files.  One scenario is my RadioShark which I have setup to make daily radio recordings.  The software doesn’t have any settings for how long to keep the files, so up until now I have just been manually deleting a couple dozen at a time every month or so. 

Enter Remove-OldItems, named after the built-in Remove-Item.

Full Syntax: Remove-OldItems c:\temp -pattern *.mp3 -KeepDays 7 -Leave 2 -Confirm -WhatIf

That will remove all mp3 files in c:\temp which are older than 7 days.  The Leave parameter is for when I use it for dealing with backup files and is a safeguard so that even if all of the files fall out of the date range, they won’t all be deleted. 

I have put together 32-bit and 64-bit installers, feel free to download them.  If you run it on a 64-bit system, the install will register with both the 32 and 64bit PowerShells. I can make the code available if anyone’s interested.

After installing the .msi, you can confirm the new Snapin is on the system by running get-pssnapin -registered. You should see EjiSnapin listed.After Install

Now the Snapin containing the cmdlet(s) is there, but not loaded into the current PowerShell session.  Since I’m going to be running this from a Scheduled Task, I don’t want to have to explicitly run Add-PSSnapin EjiSnapin every time I want to use it.  One quick way around this is to add that command to the system-wide PowerShell Profile located at $pshome\profile.ps1.  That’s easy enough, in an elevated PS prompt, just run notepad $pshome/profile.ps1 and add a single line Add-PSSnapin EjiSnapin and save the file.  Now every PS session will have the cmdlet ready to go.

Here’s the final result, a scheduled task with a simple command being run to clear out old files in my RadioShark directory.

task

Overall it was fairly easy, the most difficult part came with getting the installers to work correctly between 32 and 64-bit installations.  Future enhancements, if I come into a situation where I need it, may be to add processing from the pipeline so a collection of files to be deleted could be passed to the cmdlet instead of a directory path.  Might be useful, might not.

Here’s C# for doing the actual deletions.


    DirectoryInfo rootDir = new DirectoryInfo(Path);

    // anything older than Today minus KeepDays may be deleted
    DateTime protectionDate = DateTime.UtcNow.AddDays(-KeepDays);

    List candidates = rootDir.GetFiles(string.IsNullOrEmpty(Pattern) ? "*.*" : Pattern, SearchOption.TopDirectoryOnly)
        .OrderBy(f => f.LastWriteTimeUtc).ToList();

    if (Leave > 0)
    {
        // pop the last Leave files off the end (the most recent)
        candidates.RemoveRange(candidates.Count - Leave, Leave);
    }

    // now only keep those that are old enough
    candidates.RemoveAll(f => f.LastWriteTimeUtc >= protectionDate);

    // cycle and delete
    candidates.ForEach(f =>
        {
            if (ShouldProcess(f.FullName, "delete"))
            {
                try
                {
                    f.Delete();
                }
                catch (UnauthorizedAccessException ex)
                {
                    WriteWarning(String.Format("Unable to delete '{0}', UnauthorizedAccess", f.FullName));

                    // IOException can also occur, but I want that to be a termanating exception
                }

            }
            else
            {
                    // Nothing to do, ShouldProcess provided any errors/warnings/etc.
            }
        });

In the process of writing this I learned that PowerShell V2 allows you to script cmdlets.  So this could have been greatly simplified (mostly on the deployment side), but that wouldn’t have been nearly as interesting, right? 

That’s all folks. Thanks for reading.

iTunes is iAnnoying

Too bad the iPhone makes you get sucked into the world if iTunes – because it sucks.  I knew this going in, but it still isn’t fun when the limitations smack you in the face.

The limitation of which I speak is its inability to detect new files in its directories, automatically update its library database, and make it available for syncing and playing.  I spent a while fumbling around the UI looking for the option to turn it on, only to be ultimately disappointed by a few google searches. 

My initial plan was to take home movie clips (btw, MediaCoder is pretty handy..) and drop them into a directory managed by iTunes so they’d automatically get sent to the phone, but now I was going to have to add additional steps of manually adding the new videos each time they get created.  That’s just too much work and I’m too lazy.

I ran across an app or two that would do this updating for you, but instead decided to go a different route – creating a podcast that iTunes would auto-update and sync to the phone.  Tuesday night I whipped up an ASP.NET request handler (IHttpHandler) to generate feeds based on directory contents.  So now I’ve got the auto-updating capability I was initially looking for: after I create the video, I just drop it into a directory accessible by my webserver and iTunes will pick it up the next time it requests the feed.  As an added bonus, David now has a podcast for family and friends 🙂

Some more details on the code below the break.

Continue reading

Recipe Slideshows

Chef has a feature called Recipe Slideshows which allow you to view a recipe fullscreen in a PowerPoint-like format that’s much easier to read while you’re cooking than the small text of a cookbook, or the regular view of a recipe in Chef for that matter. I’ve had that feature around for a while, but I noticed that Ana never uses it!

Her main complaint was that the ingredients weren’t always displayed so she’d find herself constantly flipping between the directions and the ingredients, to the point where it was just much easier to deal with the small text of the regular recipe window. This past weekend I made a few changes – the ingredients are always displayed AND it highlights the ingredients that are used for the current step. Click for the full image:

Chef Recipe Slideshow

This is going into version 1.3 with a few other enhancements and fixes due sometime in January or February.

C# operator== overloading

I recently came to a situation where operator overloading C# (specifically the == operator) would really be beneficial. Since I’ve typically steered away from this technique, for readability and maintainability, I hadn’t had much experience with it.

My overloaded operator looks something like this:


static bool operator==(Id<T> a, Id<T> b)
{
return a.Value == b.Value;
}

That has been working just as planned for a few months now, but today I hit a snag when trying to do a null test against a variable of that class type, like:


Id<int> x;
...
if (x == null)
{
...
}

This causes a nice null reference exception at a.Value because a is null. My first thought was to test for null in the operator== method before I attempt accessing a.Value (or b.Value), like:

if (a == null)
{
return b == null;
}
else
{
return a.Value == b.Value;
}

Thinking I had the problem fixed, I reran; and quickly hit a StackOverFlowException. What the? Ooooh, the if (a == null) was causing that method to be called over and over, recursively until it blew the stack! OK, now how the heck can I test against null without the operator== being called??

After a moment of slight panic, I realized how to get around it. When doing just if (a == null), the Id class’ static overload is being called. The way out of this is to have the object class’ operator== explicitly called by making a simple change:


if ((object)a == null)
{
return ((object)b == null);
}
else
{
return a.Value == b.Value;
}

And that’s it! I now have an overload that handles null checking.