TweetFollow Us on Twitter

Horse Feathers

Volume Number: 20 (2004)
Issue Number: 7
Column Tag: Programming

QuickTime Toolkit

by Tim Monroe

Horse Feathers


In the previous article ("Tickle Me" in MacTech, June 2004), we took a look at using the Tcl scripting language and the Tk graphical user interface toolkit to build a QuickTime application. We saw how to use the QuickTimeTcl extension to add to a basic Tcl/Tk application the ability to open and display QuickTime movies. Figure 1 shows a movie displayed by our sample application, called TickLeez.

Figure 1: A movie window displayed by TickLeez (Macintosh)

In this article, I want to continue investigating QuickTimeTcl. In particular, we'll see how to configure our application to react to keyboard and operating system events. We'll also see how to implement movie editing. By the end of this article, TickLeez will incorporate all the standard movie playback and editing behaviors.

Event Bindings

Last time, we saw how to create the menu bar and menus for the TickLeez application. Later in this article, we'll learn how to adjust the state of menu items according to the current edited state of the frontmost movie window. Right now, we need to create some Tk bindings for a handful of events.

An event binding attaches a Tcl command to a specific event related to a movie window or to some other event, such as a keyboard event. The -accelerator options we specified when creating the menu items affect only the appearance of the menu items. To enable the keyboard shortcuts, we need to call the bind command, for instance like this:

bind .$winName <$appData(modKey)-n> {newDoc}

Tk also allows us to create bindings for activate and deactivate events for a window and for mouse-enter and mouse-exit events. Our complete set of event bindings is established in the setupBindings procedure, shown in Listing 1.

Listing 1: Setting up key bindings

proc setupBindings {winName} {
   global appData
   bind .$winName <$appData(modKey)-n> {newDoc}
   bind .$winName <$appData(modKey)-o> {openDoc}
   bind .$winName <$appData(modKey)-q> {exit}
   if {[isMovieWindow $winName]} {
      # window state-change bindings
      bind .$winName <Activate> {adjustMenus}
      bind .$winName <Deactivate> {adjustMenus}
      # accelerator key bindings
      bind .$winName <$appData(modKey)-w> {closeDoc}
      bind .$winName <$appData(modKey)-s> {saveDoc}
      bind .$winName <$appData(modKey)-S> {saveAsDoc}
      bind .$winName <$appData(modKey)-z> {undoDoc}
      bind .$winName <$appData(modKey)-x> {editDoc cut}
      bind .$winName <$appData(modKey)-c> {editDoc copy}
      bind .$winName <$appData(modKey)-v> {editDoc paste}
      bind .$winName <$appData(modKey)-a> {selectDoc all}
      bind .$winName <$appData(modKey)-b> {selectDoc none}
      bind .$winName <$appData(modKey)-KeyPress-1> \
                                                {puts "TO BE PROVIDED"}
      # miscellaneous bindings
      bind .$winName <Delete> {editDoc cut}
      bind .$winName <KeyPress> "handleKey $winName %K"
      bind .$winName <Leave> ".$winName configure \
                                                -cursor arrow"

Note the Leave binding: it's mainly intended for QuickTime VR movies, where the cursor is not automatically changed to the normal arrow cursor when it moves outside of the movie rectangle. (Other media types that alter the cursor, such as Flash, do not have this problem, so one could reasonably consider the VR behavior to be a bug.) Keep in mind that this workaround is not perfect: the cursor does not change to an arrow until the cursor hotspot has completely exited the movie window. This means that it will remain as the current VR cursor if moved into the window's title bar. Addressing that issue is left as an exercise for the reader.

Movie Playback

Once we've loaded a movie into a movie window (using the configure command), QuickTimeTcl takes care of all the nitty-gritty details of passing user or system events to the movie and making sure it reacts appropriately to those events. Mouse events on the movie controller bar work fine. Moreover, QuickTimeTcl takes care of tasking the movie often enough to ensure uninterrupted playback of linear movies or smooth user interaction with nonlinear movies like QuickTime VR movies or wired sprite movies.

Handling Keyboard Events

QuickTimeTcl, however, does not appear to provide built-in support for the standard methods of controlling movie playback using the keyboard. With a linear movie, for instance, pressing the space bar should toggle the current play state of the movie. And with a QuickTime VR movie, pressing the left arrow key should pan the movie to the left.

As you've probably guessed, we can support these behaviors by creating the appropriate event bindings. The setupBindings function considered just above binds key presses to the handleKey function, like so:

bind .$winName <KeyPress> "handleKey $winName %K"

The "%K" keyword is replaced with the keysym, which is a special Tk designator for a key on the keyboard. For instance, the keysym for the space bar is "space", and the keysym for the Shift key is "Shift_L".

Our implementation of handleKey, shown in Listing 2, first determines whether the specified movie window is a QuickTime VR movie or not. (The command ispanoramic is slightly misnamed, as it also returns 1 for a QuickTime VR object movie.) For a QuickTime VR movie, we use the movie widget commands pan, tilt, and fieldofview to adjust the view parameters. For linear movies, we use the commands step, play, and stop to adjust the movie time and play rate. We also adjust the movie's volume when we receive an up arrow or down arrow key.

Listing 2: Handling key presses

proc handleKey {winName key} {
   global appData
   set movie $appData($winName,movie)
   if {[$movie ispanoramic]} {
      # handle QTVR movie controller key bindings 
      # (and, yes, "ispanoramic" is true for object movies too)
      switch $key {
         "Right" {$movie pan [expr [$movie pan] - 10]}
         "Left" {$movie pan [expr [$movie pan] + 10]}
         "Up" {$movie tilt [expr [$movie tilt] + 10]}
         "Down" {$movie tilt [expr [$movie tilt] - 10]}
         "Shift_L" {$movie fieldofview [expr [$movie \
                              fieldofview] - 5]}
         "Control_L" {$movie fieldofview [expr [$movie \
                              fieldofview] + 5]}
   } else {
      # handle standard movie controller key bindings
      switch $key {
         "Right" {$movie step 1}
         "Left" {$movie step -1}
         "Up" {$movie configure -volume [min 255 \
                  [expr 64 + [$movie cget -volume]]]}
         "Down" {$movie configure -volume [max 0 \
                  [expr -64 + [$movie cget -volume]]]}
         "space" {if {[$movie rate] == 0} {$movie play} 
                                                else {$movie stop}}

Installing a Movie Controller Callback Function

At this point, TickLeez can open and display QuickTime movies, and it can handle all the standard means of user interaction with the movie. Before we move on to consider how to support movie editing, I should mention that QuickTimeTcl provides a way to observe and possibly override actions associated with the movie; that is to say, it provides a wrapper for QuickTime's movie controller action filter function.

We installed this movie controller callback function when we configured our movie widget, by passing a procedure name to the -mccommand argument:

.$ configure -mccommand controllerProc \
               -mcedit 1 -resizable 1

The specified procedure is passed the name of the movie widget, a string representing the action, and a possibly empty list of parameters associated with that action. For linear movies, these actions include activate, customButtonClick, deactivate, key, goToTime, mouseDown, play, setSelectionBegin, setSelectionDuration, and setVolume. For QuickTime VR movies, these actions also include pan, tilt, fieldofview, and triggerhotspot. Listing 3 shows the basic form of a movie controller callback function.

Listing 3: Handling movie controller actions

proc controllerProc {w what {par {}}} {
   if {![isMovieWindow [string range $w 1 end]]} {
   if {$what == "key"} {
      puts "got key event in controller action proc"

Normally the action is processed by the movie controller after our callback procedure returns. To suppress an action, we can execute this line of code:

return -code 3

Movie Editing

QuickTimeTcl provides a number of movie widget commands for performing the standard movie editing operations (cut, copy, paste, and so forth). It also provides support for multilevel undo, that is, the ability to undo more than one previous editing operation. None of the QuickTime-savvy applications that we've built hitherto supports this very nice feature, except for the MooVeez application we built in an earlier article, where the multilevel undo is provided by the Cocoa application framework. (See "The Cocoanuts" in MacTech, December 2002.) In this section, we'll see how to implement editing in TickLeez and how to adjust the File and Edit menus in accordance with the edited state of the frontmost movie window.

Handling Editing Operations

We've already seen how to invoke an edit command when the appropriate menu item is selected. For instance, in the setupMenus procedure (Listing 4 in the previous article), we saw this line of code for setting up the Clear menu item:

$m add command -label "Clear" -command {editDoc clear}

So, when the user selects the Clear menu item, the editDoc procedure is called with the "clear" parameter. Listing 4 shows our implementation of the editDoc procedure.

Listing 4: Editing a movie

proc editDoc {op} {
   global appData
   set winName [topMovieWindow]
   $appData($winName,movie) $op
   if {$op != "copy"} {
      set n [incr appData($winName,undoLevel)]
      set appData($winName,undoOp,$n) $op
      setWindowDirty $winName 1 
   adjustSize $winName

The key step here is the line of code that sends the specified operation string $op to the frontmost movie widget as a command. The movie widget supports these editing commands: cut, copy, paste, clear, add, and undo. Notice that we also increment the widget's undo level and store the operation string itself in the movie window's global data array. In a moment, we'll see how these items are used to support multilevel undo.

The editDoc function also calls the setWindowDirty function (shown in Listing 5) to mark the movie window as having been changed. (Note that QuickTimeTcl provides a built-in procedure haschanged that we could use instead of reading this stored value; however, I prefer to keep track of changes to the movie myself.)

Listing 5: Marking a movie window as changed

proc setWindowDirty {winName state} {
   global appData
   set appData($winName,dirty) $state
   if {[string match "mac*" $appData(os)]} {
      wm attributes .$winName -modified $state

Notice that, on Macintosh computers, we also set the modified attribute of the movie window; on Mac OS X, this has the effect of drawing a dot inside the window's close button, as shown in Figure 2.

Figure 2: A modified movie window

Undoing Editing Operations

Whenever an editing operation is performed, QuickTimeTcl adds information about the state of the movie just prior to the edit to an edit stack. The number of the topmost item on the stack is called the undo level. When a movie is first opened, its undo level is 0. Subsequent editing operations increment the undo level.

QuickTimeTcl allows us to undo one or more edits by executing the undo command. This command requires one parameter, which specifies the undo level we want to revert to. In TickLeez, we shall always revert to the previous edit, so we'll decrement the undo level by one and pass that number to undo. This is how we implement multilevel undo. Listing 6 shows our definition of the undoDoc function.

Listing 6: Undoing an edit

proc undoDoc {} {
   global appData
   set winName [topMovieWindow]
   if {$appData($winName,undoLevel) > 0} {
      incr appData($winName,undoLevel) -1
      $appData($winName,movie) undo \
   if {$appData($winName,undoLevel) == 0} {
      setWindowDirty $winName 0 

As you can see, if the user undoes all edits (so that the undo level reaches 0 once again), we call setWindowDirty with the parameter 0 to mark the window as not dirty.

Selecting All or None of a Movie

The Edit menu in TickLeez contains the Select All and Select None menu items. In previous articles, we've seen how to handle those items quite easily. For instance, we can handle the Select All item by setting the beginning of the movie selection to movie time 0 and the duration of the movie selection to the duration of the entire movie.

QuickTimeTcl provides the select command that we can use to set the movie selection to a specified range, but it does not provide a command that returns the duration of a movie directly. Instead, QuickTimeTcl provides the gettime command, which returns an array of four movie-related times: the current time, the length of the movie, the movie time scale, and the movie poster time. For a specific movie window, we can retrieve that array like this:

array set timeArr [$appData($winName,movie) gettime]

Once we've successfully done that, we can read the movie duration by looking at the $timeArr(-movieduration) element in the array; and we can read the current movie time by looking at the $timeArr(-movietime) element. Then we can handle the two selection menu items using the selectDoc function, defined in Listing 7.

Listing 7: Selecting all or none of a movie

proc selectDoc {op} {
   global appData
   set winName [topMovieWindow]
   array set timeArr [$appData($winName,movie) gettime]
   switch -- ${op} {
       all {$appData($winName,movie) select \
               0 $timeArr(-movieduration)}
       none {$appData($winName,movie) select \
               $timeArr(-movietime) 0}

Enabling and Disabling Menu Items

As you know, we need to adjust some of the items in the File and Edit menus based on the current state of the frontmost movie window (if one exists). For instance, if a movie has been edited, we need to enable the Save menu item in the File menu so that the user can save those changes, if desired. Listing 8 shows our implementation of the adjustMenus function, which is called by many of the editing functions we've encountered recently. We handle the Save menu item by looking at the dirty field of the stored movie window data, like this:

if {$appData($winName,dirty) == 1} {
   $bar.file entryconfigure "Save" -state active}

Here, we use Tk's entryconfigure command to set the state of a menu item.

We can determine whether other menu items should be enabled or disabled by executing the controllerinfo command. Like the gettime command we just considered, controllerinfo fills an array with a set of entries, in this case with entries that indicate the current state of the movie controller.

array set infoArr [$appData($winName,movie) controllerinfo]

For instance, if the $infoArr(-cutavailable) item is 1, then we want to enable the Cut menu item.

Listing 8: Adjusting the menus and menu items

proc adjustMenus {} {
   global appData
   set winName [topMovieWindow]
   set bar .${winName}mbar
   if {[string equal $appData(os) "windows"]} {
      if {[string equal $winName ""]} {
   # set the default state
   $bar.file entryconfigure "New" -state active
   $bar.file entryconfigure "Open..." -state active
   $bar.file entryconfigure "Close" -state disabled
   $bar.file entryconfigure "Save" -state disabled
   $bar.file entryconfigure "Save As..." -state disabled
   $bar.edit entryconfigure "Undo" -state disabled
   $bar.edit entryconfigure "Cut" -state disabled
   $bar.edit entryconfigure "Copy" -state disabled
   $bar.edit entryconfigure "Paste" -state disabled
   $bar.edit entryconfigure "Clear" -state disabled
   $bar.edit entryconfigure "Select All" -state disabled
   $bar.edit entryconfigure "Select None" -state disabled
   $ entryconfigure "Hide Controller Bar" \
            -state disabled
   if {[string equal $appData(os) "windows"]} {
      $ entryconfigure "About TickLeez" -state active
   } else {
      $ entryconfigure "About TickLeez" \
            -state active
   if {[isMovieWindow $winName]} {
      $bar.file entryconfigure "Close" -state active
      $bar.file entryconfigure "Save As..." -state active
      $bar.edit entryconfigure "Select All" -state active
      $bar.edit entryconfigure "Select None" -state active
      if {$appData($winName,dirty) == 1} {
         $bar.file entryconfigure "Save" -state active}
      array set infoArr [$appData($winName,movie) \
      if {$appData($winName,undoLevel) > 0} {
         $bar.edit entryconfigure "Undo" -state active}
      if {$infoArr(-cutavailable) == 1} {
         $bar.edit entryconfigure "Cut" -state active}
      if {$infoArr(-copyavailable) == 1} {
         $bar.edit entryconfigure "Copy" -state active}
      if {$infoArr(-pasteavailable) == 1} {
         $bar.edit entryconfigure "Paste" -state active}
      if {$infoArr(-clearavailable) == 1} {
         $bar.edit entryconfigure "Clear" -state active}
      if {$appData($winName,undoLevel) > 0} {
         set op \ $appData($winName,undoOp,$appData($winName,undoLevel))
         $bar.edit entryconfigure "Undo*" -label \
                                    "Undo [string totitle $op]"
      $ entryconfigure "Hide Controller Bar" \
            -state active

File Manipulation

Our final task before wrapping up TickLeez for delivery to end users is to handle the document-related operations -- that is saving an edited movie, saving a movie into a new file, closing a movie window, and ultimately quitting the application itself. As we've seen in previous articles, we need to track the state of a movie and prompt the user to save or discard changes to it when the movie window is to be closed or the application is to be quit.

Closing a Movie Window

When the user selects the Close menu item in the File menu (or types the appropriate keyboard shortcut), TickLeez executes the closeDoc procedure, which is defined in Listing 9.

Listing 9: Handling the Close menu item

proc closeDoc {} {
   attemptClose [topMovieWindow] closing

As you can see, closeDoc finds the name of the frontmost movie window and passes that name as an argument to the attemptClose function, along with the action name "closing". The attemptClose function needs to look at the dirty state of the window and, if necessary, display a dialog box asking the user to save or discard the changes to the movie. Listing 10 shows our definition of attemptClose.

Listing 10: Prompting the user to save a changed movie

proc attemptClose {winName action} {
   global appData
   set closeWindow 1
   if {$appData($winName,dirty) == 1} {
      set movieName [file tail $appData($winName,fileName)]
      set answer [tk_messageBox \
         -parent .$winName \
         -title "Save changes before $action" \
         -message "Do you want to save the changes you made \
                     to the document \u201C$movieName\u201D \
                     before $action?" \
         -type yesnocancel \
         -icon warning]
      switch $answer {
         yes         {set closeWindow [saveDoc]}
         cancel   {set closeWindow 0}
         no          {set closeWindow 1}
   if {$closeWindow == 1} {disposeDoc $winName}
   return $closeWindow

We display the Save Changes dialog box by calling the tk_messageBox function, this time with the yesnocancel type. Figure 3 shows the Macintosh dialog box, and Figure 4 shows the Windows dialog box.

Figure 3: The Save Changes dialog box of TickLeez (Macintosh)

Figure 4: The Save Changes dialog box of TickLeez (Windows)

Notice in Listing 10 that if the user selects Yes, we call the saveDoc procedure (defined later) and then set the closeWindow variable to the value it returns. We set the closeWindow variable to 1 if the user selects No and to 0 if the user selects Cancel. If closeWindow is 1, we call the disposeDoc function, defined in Listing 11.

Listing 11: Disposing a movie window and its associated data

proc disposeDoc {winName} {
   global appData
   if {![isMovieWindow $winName]} {return}
   destroy .$winName
   array unset appData $winName,*

The key step in disposeDoc is to call the Tk function destroy, which removes the specified window from the screen and dispose of any memory it occupies. We also call the array unset command to remove from the appData associative array any elements associated with the movie window.

Saving a Changed Movie

As we've seen, TickLeez calls the saveDoc function when the user selects the Save menu item (or types the appropriate keyboard equivalent). In addition, the attemptClose method (Listing 10) calls the saveDoc function if the user elects to save the changes to a window that is about to close. It's easy to implement saveDoc, using the save command provided by QuickTimeTcl, as shown in Listing 12.

Listing 12: Saving a movie

proc saveDoc {} {
   global appData
   set winName [topMovieWindow]
   # if the movie file is in our temporary directory, alert the user
   if {[string compare \
      -length [string length $appData(tempDir)] \
      $appData($winName,fileName) $appData(tempDir)] == 0} {
      tk_messageBox \
         -parent .$winName \
         -title "Warning" \
         -message "Cannot save this movie into the current \
            folder.\nPlease choose \u201CSave As...\u201D to \
            select a different folder." \
         -type ok \
         -icon warning
      return    0
   $appData($winName,movie) save
   setWindowDirty $winName 0 
   return 1

Recall that QuickTimeTcl requires a filename for each open movie and that we create a temporary file when the user selects the New command in the File menu. If the file we are saving is located in the designated temporary directory, we want to display the alert sheet shown in Figure 5 to force the user to save the file elsewhere.

Figure 5: The bad directory alert sheet

Saving a Movie into a New File

When the user selects the Save As menu item in the File menu, we need to elicit a location for the new movie file and then save the movie into that file. In TickLeez, we'll execute this line of code:

set newFile [tk_getSaveFile]

The tk_getSaveFile function displays a dialog box like the one shown in Figure 6. It returns as its result the full pathname of the specified file, or an empty string if the user did not specify a file.

Figure 6: The file-saving dialog box displayed by Tk

If the user does specify a file, we can write the movie into that file by calling the QuickTimeTcl command flatten, as shown in Listing 13

Listing 13: Saving a movie into a new file

proc saveAsDoc {} {
   global appData
   set winName [topMovieWindow]
   set newFile [tk_getSaveFile]
   if {$newFile != ""} {
      $appData($winName,movie) flatten $newFile
      $appData($winName,movie) configure -file $newFile
      wm title .$winName [file tail $newFile]
      set appData($winName,dirty) 0   
      set appData($winName,fileName) $newFile   
      set appData($winName,undoLevel) 0
      setWindowDirty $winName 0 

As you know, the standard behavior of a Save As operation is for the new movie to replace the existing movie in the existing movie window. Accordingly, saveAsDoc calls the QuickTimeTcl command configure with the full pathname of the new movie file. Then it resets the window title and several fields of the global data array associated with the movie.

Quitting the Application

When the user decides to quit TickLeez, we need to perform the standard quitting-time operations (such as making sure the user saves or discards any unsaved changes to the movie windows). When the user selects the Quit menu item, Tcl calls its own exit function, which performs any Tcl-specific cleanup tasks. We can make sure that our own cleanup tasks are performed prior to that by renaming the exit function to some other name, like this:

rename exit __exit

Then we can define our own exit function, as shown in Listing 14.

Listing 14: Quitting the application

proc exit {} {

The TickLeez function quitApp is shown in Listing 15. After we've inspected all movie windows and made sure that all changes have been saved, we remove the temporary directory we created earlier. Then we call __exit to let Tcl perform its cleanup tasks.

Listing 15: Handling the Quit menu item

proc quitApp {} {
   global appData
   set cancelled 0
   while {([topMovieWindow] != "") && ($cancelled == 0)} {
      set cancelled [expr ![attemptClose [topMovieWindow] \
   if {$cancelled == 0} {
      # remove the temp directory if it exists
      if {[file exists $appData(tempDir)]} {
         file delete -force $appData(tempDir)


This brings us to the end of our investigation of Tcl/Tk and QuickTimeTcl as a delivery vehicle for QuickTime applications. In just under four hundred lines of script (not counting the blank lines and comments in the file TickLeez.tcl), we've managed to construct a multi-window QuickTime playback and editing application that runs on both Macintosh and Windows computers. TickLeez exhibits all the standard user-interaction and document-related behaviors that we've come to expect of a QuickTime application, and it does so with a minimum of platform-specific code. I think that QuickTimeTcl provides a very nice wrapper for the underlying QuickTime APIs. Better still, its source code is freely available and can be easily modified to add capabilities that it does not currently provide. Neither Tcl/Tk nor QuickTimeTcl is perfect, but all three packages are under active development and promise to get even better as time goes by.


Thanks are due once again to Jim Ingham and to Mats Bengtsson for reviewing a draft of this article and for providing invaluable feedback.

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


Community Search:
MacTech Search:

Software Updates via MacUpdate

BetterTouchTool 2.305 - Customize multi-...
BetterTouchTool adds many new, fully customizable gestures to the Magic Mouse, Multi-Touch MacBook trackpad, and Magic Trackpad. These gestures are customizable: Magic Mouse: Pinch in / out (zoom... Read more
calibre 3.8.0 - Complete e-book library...
Calibre is a complete e-book library manager. Organize your collection, convert your books to multiple formats, and sync with all of your devices. Let Calibre be your multi-tasking digital librarian... Read more
Carbon Copy Cloner 5.0.2 - Easy-to-use b...
Carbon Copy Cloner backups are better than ordinary backups. Suppose the unthinkable happens while you're under deadline to finish a project: your Mac is unresponsive and all you hear is an ominous,... Read more
Evernote 6.12.3 - Create searchable note...
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
Default Folder X 5.1.6 - Enhances Open a...
Default Folder X attaches a toolbar to the right side of the Open and Save dialogs in any OS X-native application. The toolbar gives you fast access to various folders and commands. You just click on... Read more
Geekbench 4.1.2 - Measure processor and...
Geekbench provides a comprehensive set of benchmarks engineered to quickly and accurately measure processor and memory performance. Designed to make benchmarks easy to run and easy to understand,... Read more
GraphicConverter 10.5 - $39.95
GraphicConverter is an all-purpose image-editing program that can import 200 different graphic-based formats, edit the image, and export it to any of 80 available file formats. The high-end editing... Read more
Dropbox 35.4.20 - Cloud backup and synch...
Dropbox is an application that creates a special Finder folder that automatically syncs online and between your computers. It allows you to both backup files and keep them up-to-date between systems... Read more
XMind 8 Update 4 - Popular mind mapping...
XMind is the most popular mind mapping tool. Millions of people use XMind to clarify thinking, manage complex information, run brainstorming and get work organized. It couldn't be easier to get... Read more
Safari Technology Preview 11.1 - The new...
Safari Technology Preview contains the most recent additions and improvements to WebKit and the latest advances in Safari web technologies. And once installed, you will receive notifications of... Read more

The best new games we played this week -...
It's pretty much been one big release after another. We were privy to a bunch of surprises this week, with a lot of games we'd been waiting for quite some time dropping unexpectedly. We hope you're free this weekend, because there is a lot for... | Read more »
Stormbound: Kingdom Wars guide - how to...
Stormbound: Kingdom Wars is an excellent new RTS turned card battler out now on iOS and Android. Lovers of strategy will get a lot of enjoyment out of Stormbound's chess-like mechanics, and it's cardbased units are perfect for anyone who loves the... | Read more »
The best AR apps and games on iOS right...
iOS 11 has officially launched, and with it comes Apple's ARKit, a helpful framework that makes it easier than ever for developers to create mobile AR experiences. To celebrate the occassion, we're featuring some of the best AR apps and games on... | Read more »
Phoenix Wright: Ace Attorney - Spirit of...
Phoenix Wright: Ace Attorney - Spirit of Justice 1.00.00 Device: iOS Universal Category: Games Price: $.99, Version: 1.00.00 (iTunes) Description: ************************************************※IMPORTANT※・Please read the “When... | Read more »
Kpressor (Utilities)
Kpressor 1.0.0 Device: iOS Universal Category: Utilities Price: $4.99, Version: 1.0.0 (iTunes) Description: The ultimate ZIP compression application for iPhone and iPad. - Full integration of iOS 11 with support for multitasking.-... | Read more »
Find out how you can save £35 and win a...
Nothing raises excitement like a good competition, and we’re thrilled to announce our latest contest. We’ll be sending one lucky reader and a friend to the Summoners War World Arena Championship at Le Comedia in Paris on October 7th. It’s the... | Read more »
Another Lost Phone: Laura's Story...
Another Lost Phone: Laura's Story 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: Another Lost Phone is a game about exploring the social life of a young woman whose phone you have just... | Read more »
The Witness (Games)
The Witness 1.0 Device: iOS Universal Category: Games Price: $9.99, Version: 1.0 (iTunes) Description: You wake up, alone, on a strange island full of puzzles that will challenge and surprise you. You don't remember who you are, and... | Read more »
Egg, Inc. guide - how to build your gold...
Egg, Inc.'s been around for some time now, but don't you believe for one second that this quirky clicker game has gone out of style. The game keeps popping up on Reddit and other community forums thanks to the outlandish gameplay (plus, the... | Read more »
The best deals on the App Store this wee...
Good news, everyone! Your favorite day of the week has arrived at last -- it's discount roundup day! This fine Wednesday evening we're gathering up the hottest deals on the App Store. We've got action platformers, we've got puzzle games, we've got... | Read more »

Price Scanner via

Apple Offering Up To $455 Credit Toward iPhon...
iPhone 8 and 8 Plus are now available at the Apple Store, and you can receive up to $375 credit toward a new iPhone purchase when you trade in your eligible smartphone. Photo Courtesy Apple Just... Read more
AnyTrans Offers iOS Users Three Ways For Movi...
iMobie Inc. today announceed AnyTrans v6.0.1, which now can help iOS users move all data to iPhone 8/8 Plus seamlessly. The software is available both on Mac and Windows and fully able to move all... Read more
Snag a 13-inch 2.3GHz MacBook Pro for $100 of...
B&H Photo has 2017 13″ 2.3GHz MacBook Pros in stock today and on sale for $100 off MSRP, each including free shipping plus NY & NJ sales tax only: – 13-inch 2.3GHz/128GB Space Gray MacBook... Read more
Verizon offers new iPhone 8 for $100-$300 off...
Verizon is offering the new iPhone 8 for up to $300 off MSRP with an eligible trade-in: • $300 off: iPhone 6S/6S Plus/7/7 Plus, Google Pixel XL, LG G6, Moto Z2 Force, Samsung Galaxy S7/S7 edge/S8/S8... Read more
Apple Refurbished 2017 13-inch MacBook Pros a...
Apple has Certified Refurbished 2017 13″ Touch Bar MacBook Pros in stock today and available for $200-$300 off MSRP. A standard Apple one-year warranty is included with each MacBook, and shipping is... Read more
OWC USB-C Travel Dock with 5 Ports Connectivi...
OWC have announced the new OWC USB-C Travel Dock, the latest addition to their line of connectivity solutions. The USB-C Travel Dock lets you connect its integrated USB-C cable to a Mac or PC laptop... Read more
Pelican Products, Inc. Unveils Cases For All...
Pelican Products, Inc. has announced the launch of its full line of cases including Voyager, Adventurer, Protector, Ambassador, Interceptor (for the Apple iPhone 8 and 8 Plus backwards compatible... Read more
$100 off new 2017 13-inch MacBook Airs
B&H Photo has 2017 13″ MacBook Airs on sale today for $100 off MSRP including free shipping. B&H charges NY & NJ sales tax only: – 13″ 1.8GHz/128GB MacBook Air (MQD32LL/A): $899, $100 off... Read more
Apple restocks Certified Refurbished 13-inch...
Apple has Certified Refurbished 2015 13″ MacBook Airs available starting at $719 and 2016 models available starting at $809. An Apple one-year warranty is included with each MacBook, and shipping is... Read more
Is iPhone X Really The Future Of The Smartpho...
Should iPhone X even be called a telephone? It does of course support telephony and texting, but its main feature set is oriented to other things. It is also debatable whether it makes any rational... Read more

Jobs Board

Specialist - Retail Customer Services and Sal...
The position listed below is not with Tennessee Interviews but with Apple , Inc. Tennessee Interviews is a private organization that works in collaboration with Read more
Specialist - Retail Customer Services and Sal...
The position listed below is not with South Carolina Interviews but with Apple , Inc. South Carolina Interviews is a private organization that works in collaboration Read more
Behavior Technician with *Apple* Consulting...
The position listed below is not with Washington Interviews but with APPLE CONSULTING Washington Interviews is a private organization that works in collaboration Read more
Infection Control RN with *Apple* Rehab - A...
The position listed below is not with Georgia Interviews but with Apple Rehab Georgia Interviews is a private organization that works in collaboration with Read more
Specialist - Retail Customer Services and Sal...
The position listed below is not with South Carolina Interviews but with Apple , Inc. South Carolina Interviews is a private organization that works in collaboration Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.