QuickTime Toolkit

Back To The Future, Part II

by Tim Monroe

Developing Applications With The QuickTime For Cocoa Kit

In the previous QuickTime Toolkit article ("Back to the Future" in MacTech, May 2005), we began looking at
Apple's new Cocoa framework for displaying and modifying QuickTime movies, called the QuickTime For Cocoa Kit
or the QTKit. We saw how to open and display a movie in a window of a Cocoa document-based application; we
also saw how to manipulate movies using command-line tools, which would be quite useful for batch processing
via shell scripts or other scripting mechanisms.

Introduction

In this article, we'll continue our investigation of the QTKit framework, which is available in QuickTime 7
on both Panther and Tiger. We'll see how to extend the sample application KitEez that we began developing in
the previous article to support the complete set of standard document behaviors (Save, Save As, Revert, and so
forth). Toward the end of this article, we'll see how to restrict the file types displayed in the file-opening
dialog box. Then in the next article, we'll wrap up our tour of the QTKit by looking at some advanced uses of
its classes and methods.

Document Behaviors

So far, our sample application KitEez is able to open any kind of file that QuickTime can handle -- standard
movies files, Flash files, MP3 files, MPEG-4 files, AIFF files, text files, and so forth -- and display the
movie data in a Cocoa document window. Figure 1 shows a typical KitEez document window. As you can see, the
movie and the movie controller bar completely fill the content region of the window. As you can also see from
the hourglass shape of the thumb in the movie controller bar, the movie is editable using the items in the
Edit menu or their standard keyboard shortcuts.

Figure 1. A window that
contains a QTMovieView

Because movies opened using KitEez are editable, we'll want to support all the standard document behaviors:
Undo/Redo, Save, Save As, Revert to the last saved version, and so forth. If you have developed Cocoa
document-based applications before, then you'll know that Cocoa provides a sophisticated document architecture
that tracks changes to a document and responds appropriately to user actions. For instance, if the user tries
to close an edited but unsaved document window, Cocoa will display a sheet that prompts the user to save or
discard those changes. The Cocoa document architecture, however, has no knowledge of what it means to save a
QuickTime movie, so we'll need to override a few NSDocument methods to add that and other standard document
behaviors to our sample application.

Supporting Editing Operations

It's actually trivially easy to support the standard undo and redo mechanism for edits made to a QuickTime
movie that is displayed in a QTMovieView in a Cocoa document window. All we need to do is make the associated
QTMovie object editable, and we saw how to do this in the previous article with this single line of code:

Once we've executed this line of code, the movie can be edited using QTMovieView methods like cut:, copy:,
paste:, trim:, and the like. Indeed, the default behavior of the Edit menu items is to issue these IB actions,
so we need to write exactly 1 line of code (shown above) to have a full-fledged movie editing application.

QTKit provides the standard multiple-level undo and redo processing. A user can cut, copy, and paste to his
or her heart's content and then undo all those editing operations. Also, QTKit automatically provides the
standard drag-and-drop editing operations. A user can drag a movie segment out of a movie window and into any
other object that can accept dragged movie data. Figure 2 shows the drag image being dragged out of a movie
window.

Figure 2. A dragged movie segment

The performance of the dragging in QTKit-based applications is vastly improved over that provided by the
standard movie controller. In some benchmarks, the creation of the drag image alone was over 3000 times faster
in QTKit applications than in applications using the movie controller's drag-and-drop capability.

Saving an Edited Movie

When the user selects the Save item in the File menu, the first responder's saveDocument: method is
executed. The NSDocument implementation of this method checks to see whether a file is already associated with
the document; if not, it displays the file-saving sheet to elicit a filename and location from the user. This
will never actually happen in KitEez, since we only ever open movies from existing files. But it might happen
that an edited movie cannot be saved into the file it was opened from. For instance, KitEez is able to open
MP3 files as QuickTime movies (transparently invoking its MP3 import component), which are then fully
editable. But QuickTime does not provide an MP3 export component, so KitEez is unable to save the edited data
back into the original MP3 file. In that case, we'd want to display the file-saving sheet so that the user can
save the data as a QuickTime movie file (.mov).

The QTMovie class provides a method that we can use to determine whether a movie object can be saved into
its associated file, canUpdateMovieFile. Listing 1 shows our override of the saveDocument: method.

This is simple enough: if the movie can be saved into the file it was opened from, then we just call
NSDocument's saveDocument: method; otherwise we call its saveDocumentAs: method.

NSDocument's saveDocument: and saveDocumentAs: methods internally call
writeWithBackupToFile:ofType:saveOperation: to actually write the document data into the associated file. We
can override that method to save the edited movie data into the original movie file or into the newly-selected
destination file. Listing 2 shows our override method.

When the requested operation is NSSaveOperation, we simply call the updateMovieFile method to update the
movie atom in the movie file. When the requested operation is NSSaveAsOperation, we need to do a little more
work. As you can see, we first call the QTMovie method writeToFile:withAttributes: with a nil dictionary of
attributes. This has the effect of writing only the movie atom into the destination file. What we end up with
in this case is a reference movie, that is, a movie whose media data is located in some other file. If instead
we wanted a self-contained movie file, we could call writeToFile:withAttributes: with a dictionary that
indicates that we want the movie to be flattened into the destination file, like this:

I'll leave it as an easy exercise for the reader to add an accessory view to the save panel that allows the
user to determine whether a movie is saved as a reference movie or as a self-contained movie, like the one
displayed by the QuickTime Player application (Figure 3).

Figure 3. An accessory view in a save panel

As you know, the standard behavior when performing a Save As operation is to replace the movie in the movie
view with the movie in the new destination file. So, once we've called writeToFile:withAttributes:, we then
need to open the movie in the new file and set it as the movie displayed in the movie view. Then we need to
perform any movie configuration that must happen when a movie is opened. As you can see, we call the method
initializeMovieWindow, defined in Listing 3. This code is lifted wholesale from the
windowControllerDidLoadNib: method we considered in the previous article on QTKit.

It's perhaps worth mentioning that the writeWithBackupToFile:ofType:saveOperation: method is deprecated in
Mac OS X version 10.4 and later. Since however we want our application to run under all environments
supporting QTKit, including Mac OS X version 10.3.9, we'll stick with this method.

Reverting to the Last Saved Version of a Movie

There remains just one document behavior for us to implement, namely reverting to the last saved version of
a movie file. When the user selects the Revert item in the File menu, the Cocoa document handling code
displays the sheet shown in Figure 4.

Figure 4. The Revert sheet

If the user presses the Revert button, the revertDocumentToSaved: method in the first responder is invoked.
We won't override that method, so that method in the NSDocument class will be called. Rather, we'll override
the revertToSavedFromFile:ofType: method, as shown in Listing 4.

As in the Save As case shown in Listing 3, we open the specified file and assign it to the movie view; then
we perform the required initialization of the movie and movie window. Also, we return the value YES to make
sure that the change count of the document is cleared.

So, we have successfully implemented a reasonably complete set of document-related behaviors in our sample
application KitEez, using just a very few QTMovie methods: canUpdateMovieFile, updateMovieFile, and
writeToFile:withAttributes:. At no point did we need to step outside the methods provided by QTKit into the
underlying Carbon APIs. This stands in stark contrast to the work we needed to do in our earlier Cocoa
movie-playing application MooVeez, which relied on the now-deprecated Cocoa classes NSMovie and NSMovieView
for its QuickTime support. I invite you to take a second look at the article describing those classes ("The
Cocoanuts" in MacTech, December 2002); by comparing the Carbon-laced methods we had to write there with the
purely Cocoa-based methods we've seen here, you will get a very good appreciation of how big an advancement
the QTKit is over those earlier classes.

Openable File Types

In the previous article introducing QTKit, we saw that we can very easily configure the file-opening dialog
box to list all files openable by QuickTime by overriding the panel:shouldShowFilename: method and calling the
canInitWithFile: class method. That method returns YES just in case a specified file can be used to initialize
a QTMovie object. For certain purposes, however, we might want to restrict the types of files that the user
can open to some more limited set. For instance, as you probably know, QuickTime can open text files with its
text movie importer -- which converts the text into a series of frames in a text track. (See "Word is Out" in
MacTech, November 2000 for more information on QuickTime's text-handling capabilities.) But it's doubtful that
most applications that can open and display QuickTime movies would want to allow text files to be opened by
the user. Ditto for HTML files. Ditto for PDF files.

QTKit provides an easy way to allow the user to open only the kinds of files that would normally be
considered as media files and hence openable by a QuickTime application. Instead of using the canInitWithFile:
method, we can use the movieFileTypes: method. This too is a class method, so you don't need to have an
existing QTMovie object in order to call it.

The movieFileTypes: method returns an NSArray of file types and file extensions that can be opened by
QuickTime. This method takes one parameter, which indicates the kinds of file types that you want to be
included in the array. Currently these flags are defined for specifying file types:

Passing the value QTIncludeCommonTypes indicates that you want the array to contain only those file types
and extensions that are commonly thought of as openable by QuickTime; this includes the extensions .mov and
.mqv, as well as any file types that can be imported in place by QuickTime. (Recall that to be able to import
a file in place is to be able to import the file without having to create a new file to hold the imported
data.)

The QTIncludeStillImageTypes flag indicates that you want the array to include, in addition to the common
file types, all types of files that can be opened by QuickTime using one of its available graphics importers.
The QTIncludeTranslatableTypes flag indicates that you want the array to include also those file types that
can be opened by QuickTime using one of its available movie importers, whether or not the file data can be
imported in place; this array excludes however any file types that would require an aggressive importer. (An
aggressive importer is one that can handle file types like text or HTML that would not normally be considered
openable by QuickTime.) Finally, the QTIncludeAggressiveTypes flag indicates that you want the array to
include file types that require an aggressive importer.

Obviously, the QTIncludeAllTypes flag sets all the bits in the options parameter and requests that the
returned array include file types and file extensions for all files that QuickTime can open, using any
available graphics or movie importer. Passing the array associated with the QTIncludeAllTypes flag to
NSOpenPanel's runModalForTypes: method is essentially identical to using the canInitWithFile: method inside
our panel:shouldShowFilename: override method.

It's important to realize that, for instance, the array returned when specifying the
QTIncludeStillImageTypes flag will include all file types and extensions for still image files as well as all
file types and extensions for the common movie types. That is to say, that array does not contain only the
file types and extensions for still image types. If you wanted an array like that, you would need to use
Component Manager functions to iterate through all installed components and select only those of type
GraphicsImporterComponentType. Listing 5 shows how you might do that.

Conclusion

In this article, we've added the standard document-handling behaviors to our KitEez sample application.
We've seen how to use QTKit methods to support saving an edited movie into its original file or into a new
file, and we've seen how to revert to the last saved version of a movie file. KitEez is now a reasonably
complete multi-document movie opening and editing application.

In the next article, we'll take a look at some of the more advanced operations we can use the QTKit
framework to perform. We'll see how to add images to an existing QuickTime movie, work with notifications and
delegates, and execute QTKit methods on a secondary thread.

Tim Monroe is a member of the QuickTime engineering team at Apple. You can contact him at
monroe@mactech.com. The views expressed here are not necessarily shared by his employer.

Community Search:

MacTech Search:

Software Updates via MacUpdate

Microsoft Office 2016 16.11 - Popular pr...

Microsoft Office 2016 - Unmistakably Office, designed for Mac.
The new versions of Word, Excel, PowerPoint, Outlook, and OneNote provide the best of both worlds for Mac users - the familiar Office... Read more

Adobe Photoshop CC 2018 19.1.2 - Profess...

Photoshop CC 2018 is available as part of Adobe Creative Cloud for as little as $19.99/month (or $9.99/month if you're a previous Photoshop customer).
Adobe Photoshop CC 2018, the industry standard... Read more

Adobe Dreamweaver CC 2018 18.1.0.10155 -...

Dreamweaver CC 2018 is available as part of Adobe Creative Cloud for as little as $19.99/month (or $9.99/month if you're a previous Dreamweaver customer).
Adobe Dreamweaver CC 2018 allows you to... Read more

Adobe Flash Player 29.0.0.113 - Plug-in...

Adobe Flash Player is a cross-platform, browser-based application runtime that provides uncompromised viewing of expressive applications, content, and videos across browsers and operating systems.... Read more

Drive Genius 5.2.0 - $79.00

Drive Genius features a comprehensive Malware Scan. Automate your malware protection. Protect your investment from any threat. The Malware Scan is part of the automated DrivePulse utility. DrivePulse... Read more

MegaSeg 6.0.6 - Professional DJ and radi...

MegaSeg is a complete solution for pro audio/video DJ mixing, radio automation, and music scheduling with rock-solid performance and an easy-to-use design. Mix with visual waveforms and Magic... Read more

ffWorks 1.0.7 - Convert multimedia files...

ffWorks (was iFFmpeg), focused on simplicity, brings a fresh approach to the use of FFmpeg, allowing you to create ultra-high-quality movies without the need to write a single line of code on the... Read more

Dash 4.1.5 - Instant search and offline...

Dash is an API documentation browser and code snippet manager. Dash helps you store snippets of code, as well as instantly search and browse documentation for almost any API you might use (for a full... Read more

Evernote 7.0.3 - Create searchable notes...

Evernote allows you to easily capture information in any environment using whatever device or platform you find most convenient, and makes this information accessible and searchable at anytime, from... Read more

jAlbum Pro 15.3 - Organize your digital...

jAlbum Pro has all the features you love in jAlbum, but comes with a commercial license. You can create gorgeous custom photo galleries for the Web without writing a line of code!
Beginner-friendly... Read more

Latest Forum Discussions

Around the Empire: What have you missed...

Oh hi nice reader, and thanks for popping in to check out our weekly round-up of all the stuff that you might have missed across the Steel Media network. Yeah, that's right, it's a big ol' network. Obviously 148Apps is the best, but there are some... | Read more »

All the best games on sale for iPhone an...

It might not have been the greatest week for new releases on the App Store, but don't let that get you down, because there are some truly incredible games on sale for iPhone and iPad right now. Seriously, you could buy anything on this list and I... | Read more »

Everything You Need to Know About The Fo...

In just over a week, Epic Games has made a flurry of announcements. First, they revealed that Fortnite—their ultra-popular PUBG competitor—is coming to mobile. This was followed by brief sign-up period for interested beta testers before sending out... | Read more »

The best games that came out for iPhone...

It's not been the best week for games on the App Store. There are a few decent ones here and there, but nothing that's really going to make you throw down what you're doing and run to the nearest WiFi hotspot in order to download it. That's not to... | Read more »

Death Coming (Games)

Death Coming 1.1.1.536
Device: iOS Universal
Category: Games
Price: $1.99, Version: 1.1.1.536 (iTunes)
Description:
--- Background Story ---You Died. Pure and simple, but death was not the end. You have become an agent of Death: a... | Read more »

Hints, tips, and tricks for Empires and...

Empires and Puzzles is a slick match-stuff RPG that mixes in a bunch of city-building aspects to keep things fresh. And it's currently the Game of the Day over on the App Store. So, if you're picking it up for the first time today, we thought it'd... | Read more »

What You Need to Know About Sam Barlow’s...

Sam Barlow’s follow up to Her Story is #WarGames, an interactive video series that reimagines the 1983 film WarGames in a more present day context. It’s not exactly a game, but it’s definitely still interesting. Here are the top things you should... | Read more »

Pixel Plex Guide - How to Build Better T...

Pixel Plex is the latest city builder that has come to the App Store, and it takes a pretty different tact than the ones that came before it. Instead of being in charge of your own city by yourself, you have to work together with other players to... | Read more »

Fortnite Will Be Better Than PUBG on Mob...

Before last week, if you asked me which game I prefer between Fortnite Battle Royale and PlayerUnknown’s Battlegrounds (PUBG), I’d choose the latter just about 100% of the time. Now that we know that both games are primed to hit our mobile screens... | Read more »

Apple is now offering Certified Refurbished 2017 10″ and 12″ iPad Pros for $100-$190 off MSRP, depending on the model. An Apple one-year warranty is included with each model, and shipping is free:
–... Read more

Silver 12″ 1.3GHz MacBook on sale at B&H...

B&H Photo has the 2017 12″ 1.3GHz Silver MacBook on sale for $1399.99 including free shipping plus sales tax for NY & NJ residents only. Their price is $200 off MSRP, and it’s the lowest... Read more

MacTech is a registered trademark of Xplain Corporation. Xplain, "The journal of Apple technology", Apple Expo, Explain It, MacDev, MacDev-1, THINK Reference, NetProfessional, Apple Expo, MacTech Central, MacTech Domains, MacNews, MacForge, and the MacTutorMan are trademarks or service marks of Xplain Corporation. Sprocket is a registered trademark of eSprocket Corporation. Other trademarks and copyrights appearing in this printing or software remain the property of their respective holders. Not responsible for typographical errors.

All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.