My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
iMedia2Doc  
Documentation and usage notes for iMedia 2 framework
Phase-Implementation, Featured
Updated Mar 16, 2010 by dan94...@gmail.com

iMedia2 Documentation

This page will host the documentation for maintainers of the iMediaBrowser.framework (version 2.x), as well as documentation for application developers using the framework in their apps. Chapters 1 and 2 are recommended reading if you want to understand the internal architecture of the framework, contribute to its future development, or write new parser classes. These chapters are also helpful if you want to customize iMediaBrowser (chapter 4). If you are an application developer that simply wants to use the standard behavior of the framework in your own app, then you can skip ahead to chapter 3.

The standard user interface of iMediaBrowser looks like this:

1. Architecture

1.1 The Model Classes

The model is divided into three groups: media types, nodes, and objects. The screenshot above shows where In the standard user interface each kind of model class is displayed.

1.1.1 Media Types

iMedia currently defines 4 different media types, but new ones can be added easily if the need arises. The constants for media types are defined in IMBCommon.h:

extern NSString* kIMBMediaTypeImage;
extern NSString* kIMBMediaTypeAudio;
extern NSString* kIMBMediaTypeMovie;
extern NSString* kIMBMediaTypeLink;

1.1.2 IMBNode

Nodes are displayed in the upper part of the standard iMediaBrowser panel. They are either displayed in an NSOutlineView or in an NSPopUpButton. The model class for a node is IMBNode. For each row in the NSOutlineView, there is an instance of IMBNode.

IMBNode is a fairly big class with lots of properties. Although almost all of these properties have setters and getters you should essentially regard instance of IMBNode as "immutable", i.e. once a node has been created and all properties are set, this node is not to be modified anymore. If for any reason a node needs to be updated with new values, a new instance is created and the original instance is replaced with the new instance. This mechanism will be described in more detail in IMBLibraryController and the chapter 2 (Writing a Parser Class).

The most important properties of IMBNode are:

@property (copy) NSString* identifier;	
@property (copy) NSString* name;	
@property (retain) NSImage* icon;	
@property (retain) NSArray* subNodes;				
@property (retain) NSArray* objects;

The identifier is a string that uniquely identifies a node in the tree. This string must be unique across media types, parsers, and across application launches, as the identifier is used for a multitude of jobs. It controls persistance of selection and expanded state, and is also responsible for replacing old with new instances.

Name and icon should be self-explanatory. These are directly visible in the user interface.

The subNodes array is used to construct a node tree. The objects array is used to represent items of a given media type, e.g. images, songs, or movies. If the subNodes or object array is nil, a node is considered to be "unpopulated" - i.e. it is in an incomplete state. Once an unpopulated node is selected or expanded in the user interface, the controllers will trigger appropriate actions to populate this node (with subNodes and objects).

1.1.3 IMBObject

IMBObject is the model class that holds information about a single media item, regardless whether it is a local file on the hard disk, a remote file on the internet, or a piece of data on an external device like a camera. IMBObjects have several properties. The most important are:

  • location Can be a path, url or any other info that uniquely identifies the location where the data is to be found.
  • name Name that is displayed in the user interface. This could be a filename or a caption.
  • icon Small icon that is displayed in list view.
  • metadata A dictionary that contains additional metadata about an object.
  • metadataDescription A string representation of the above, which can be displayed in the user interface.
  • parser A pointer back to the parser that created this IMBObject. Needed for lazy-loading thumbnail images or metadata. This pointer is mandatory!
  • imageLocation A optional path or url to the thumbnail. It may be different from location. E.g. iPhoto uses smaller JPEG files for the thumbnails.
  • imageRepresentation The thumbnail data itself. We recommend using CGImageRef as it is much faster and more efficient than NSImage.
  • imageRepresentationType The recommended type is IKImageBrowserCGImageRepresentationType.

Thumbnails are loaded asynchronously and lazily when actually needed, i.e. when they become visible while scrolling in the IKImageBrowserView. When they are scrolled out of sight, they will be unloaded once the cache reached a certain maximum size. Refer to the source code in the classes IMBObjectThumbnailLoadOperation and IMBObjectFifoCache for details.

The subclass IMBEnhancedObject contains one additional property called preliminaryMetadata. Use this property to store metadata that is instantly available at object creation time, i.e. metadata that comes "for free". This preliminaryMetadata can later be combined with additional metadata (which is then stored in the metadata property). Metadata is built lazily (like thumbnails) as object are made visible in the view.

1.1.4 IMBObjectPromise

Since objects can represent media files on the local file system, remote servers on the internet, camera devices, or possibly other locations, we need an abstraction mechanism that provides a common API to access all the media files, regardless of their location. IMBObjectPromise provides this API. IMBObjectPromise is used for double clicking, dragging, or opening media files via context menu items.

An instance of IMBObjectPromise is initialized with an array of IMBObjects (usually the selected objects, or in the case of a context menu the clicked object). Loading of the media files is triggered with the method -startLoadingWithDelegate:finishSelector:. Once loading has concluded the finishSelector is called on the delegate. This mechanism is can be used for double clicking - in this case the framework does everything for you.

IMBObjectPromise can also be used fro drag & drop operations. The IMBObjectPromise instance is created with an array of objects and then put onto the pasteboard. When you receive a drop in your own client application, you can retrieve the IMBObjectPromise instance from the pasteboard, start loading, and once the finishSelector is called, you can retrieve the downloaded files. You also have the option of implementing your own custom loading progress.

1.2 The Controller Classes

TO DO

1.2.1 IMBParser

1.2.2 IMBParserController

1.2.3 IMBLibraryController

1.2.4 IMBNodeViewController

1.2.5 IMBObjectViewController

1.2.6 IMBObjectArrayController

1.3 The View Classes

TO DO

2. Writing a Parser Class

2.1 Factory Method

+ (NSArray*) parserInstancesForMediaType:(NSString*)inMediaType;

2.2 Node Creation and Population

ATTENTION: inOldNode is readonly and is only passed in for reference, but must not be modified by the parser in a background operation. It is passed as an argument to the parser so that existing old nodes can be recreated as faithfully as possible. Must return an autoreleased object...

- (IMBNode*) nodeWithOldNode:(const IMBNode*)inOldNode options:(IMBOptions)inOptions error:(NSError**)outError;
- (BOOL) populateNode:(IMBNode*)inNode options:(IMBOptions)inOptions error:(NSError**)outError;

2.2 Object Promises

Returns a promise object that is appropriate for a given parser type. The default implemenation simply returns an IMBLocalObjectPromise. Parsers that require something else must override this method...

- (IMBObjectPromise*) objectPromiseWithObjects:(NSArray*)inObjects;

2.3 Lifetime Management

willUseParser: is called in various situations just before a parser is going to be used. Can be used to prepare the instance or update cached data...

didStopUsingParser is called after a node was deselected. The parser can release its cached data (if present)...

watchedPathDidChange : is called when a file watcher fires and it concerns a parser. Also gives a parser a chance to update any cached data...

- (void) willUseParser;
- (void) didStopUsingParser;
- (void) watchedPathDidChange:(NSString*)inWatchedPath;

LOTS MORE NEEDED HERE

3. Using the Framework in Your App

iMediaBrowser can be used with default behavior that requires very little work on your part, or it can be customized (but that requires a lot more work). The default user interface is shown at the top of this page. Using the default standalone panel in you app is pretty easy.

  1. Link your application against iMedia.framework
  2. Link your application against ObjectiveFlickr.framework. It is the responsibilty of your app to build this framework.
  3. #import <iMedia/iMedia.h>
  4. When you need the standalone panel, call the following three lines:
NSArray* mediaTypes = [NSArray arrayWithObjects:kIMBMediaTypeImage,kIMBMediaTypeAudio,kIMBMediaTypeMovie,kIMBMediaTypeLink,nil];
IMBPanelController* panelController = [IMBPanelController sharedPanelControllerWithDelegate:self mediaTypes:mediaTypes];
[panelController showWindow:nil];

You can also call sharedPanelController to return the existing panel controller, creating a default panel controller with no delegate and default media types if it's not created yet, or sharedPanelControllerWithoutLoading to return any existing panel controller, or nil if it's not loaded yet — useful if you are trying to close down the media browser if it's open.

The contents of this panel and the behavior can be customized by implementing various delegate methods. Please refer to the source code in IMBTestAppDelegate.m for examples and have a look at the headers files of the various controller classes for info on all delegate methods. There are various different controller protocols. The methods all get passed (sometimes with detours) to your delegate:

  • IMBParserControllerDelegate
  • IMBLibraryControllerDelegate
  • IMBObjectArrayControllerDelegate
  • IMBObjectViewControllerDelegate
  • IMBPanelDelegate

If the degree of customization which is possible by implementing these delegate methods does not suffice for your needs, please refer to chapter 5 to find out how you can build custom user interfaces and behaviors by manually combining the components of the framework, possibly also subclassing some classes.


3.1 Migrating from iMedia 1

(If you were using the older version of iMedia Browser, be sure to really clean out your build before trying to bring in the new imedia, so you don't have conflicts!) iMediaBrowser -> IMBPanelController iMediaBrowser sharedBrowserWithDelegate -> IMBPanelController sharedPanelControllerWithDelegate:mediaTypes:

4. Notes on Customizing and Subclassing

TO DO



History

  • 2009/10/31 PB: Created this page
  • 2009/11/01 PB: Added some content to chapter 3
  • 2010/03/12 PB: Added content to chapter 1.1.3 and chapter 3
  • 2010/03/16 DW: Merged in PB's latest, with my starts on chapter 2

Sign in to add a comment
Powered by Google Project Hosting