TweetFollow Us on Twitter

Dec 99 Getting Started

Volume Number: 15 (1999)
Issue Number: 12
Column Tag: Getting Started

Carrying On With QuickTime

by Dan Parks Sydow

More QuickTime fundamentals to prepare you for the power of Apple's digital movie system software

In last month's Getting Started article I discussed the wealth of features available to programmers interested in incorporating into their programs QuickTime capabilities. If you aren't familiar with QuickTime movie playing techniques, you should be! Last month you read about the basics of QuickTime programming. In particular, you learned how your application can open a movie from a file and then place that movie - complete with attached controller - in a window. That article closed with the mention that a movie could also be used without a movie controller. That's a technique that may be useful in a variety of circumstances, such as having a movie play in response to some user action (a game or educational program might include this feature). In this article we'll conclude our QuickTime introduction by providing the details of how your program can play a movie without the aid of a movie controller. Here you'll also see how to embed a movie in a dialog box and then use standard dialog box buttons to play the movie.

QuickTime Basics Review

Before jumping into this month's code, a short review of the very basics of QuickTime is in order. For more details, look over last month's Getting Started article. If you've read that article, though, don't skip this section. Here I also throw in one or two new tidbits of QuickTime-related code.

Apple has created the Movie Toolbox to help programmers give their applications the ability to play movies. This toolbox is a large set of movie-related functions to the system software. When you know the Movie Toolbox, you know QuickTime.

A program that makes use of QuickTime needs to verify that the user's machine has the QuickTime extension available. It should also initialize the Movie Toolbox. The following code takes care of these two tasks:

OSErr	err;
long		result;

err = Gestalt( gestaltQuickTime, &result );
if ( err != noErr )
	DoError( "\pQuickTime not present" );

err = EnterMovies(); 
if ( err != noErr )
	DoError( "\pError initializing the Movie Toolbox" ); 

Before playing a movie, a program needs to open the QuickTime file in which the movie is stored, load the movie data to memory, and then close the file.

In last month's article you saw how to use the standard Open file dialog box to give the user the opportunity to choose the movie to play. Here we'll elaborate on a technique briefly mentioned in last month's article: how a program can easily carry out the movie-opening chore "behind the scenes." That is, here we'll let the program select the movie to open. A program of course doesn't randomly open a movie - the selection is typically based on some user action. For instance, if the user chooses a Connection Setup item from a Help menu, the program would know to open a movie titled ConnectSetup.mov to display a movie that walks the user through some connection process.

To specify a movie to open, your program needs a file system specification, or FSSpec, for the file that holds the movie. The FSSpec specifies where on disk the movie file is located. If the name of the file that holds the movie is known (you're supplying the movie file, so it's name should certainly be known), and if the file is to reside in the same folder as the application, then the code to create the file's FSSpec looks like this:

#define	kApolloMovieName	"\pMovieApollo"

OSErr		err;
FSSpec		movieFileSpec;

err = FSMakeFSSpec( 0, 0, kApolloMovieName, &movieFileSpec );

In the above snippet the name of the file to open is MovieApollo (this month's example program plays two movies, including one of the launch of the Apollo rocket). With the first two arguments to FSMakeFSSpec() each set to 0, the movie is expected to be in the same folder as the application. If you'd like to group all your program's movies in a folder within the same folder that holds the application, then you'll need to include that folder's name in the third argument to FSMakeFSSpec(). Use a colon between the folder name and the file name to indicate that this is a pathname and that the first part of the name is a folder and the second part is a file name. For instance, if stored alongside the application was a folder named Movies, then the definition of the constant kApolloMovieName would become:

#define	kApolloMovieName	"\pMovies:MovieApollo"

The FSSpec returned by FSMakeFSSpec() is now used in a call to the Movie Toolbox function OpenMovieFile(). The three arguments this function requires are a pointer to the FSSpec, a pointer to a short variable that gets filled in with a file reference number, and a file-opening permission level.

short		movieRefNum;

err = OpenMovieFile( &movieFileSpec, &movieRefNum, fsRdPerm);

The movie file's data can now be loaded to memory. A call to the Movie Toolbox function NewMovieFromFile() does that:

Movie		theMovie;
OSErr		err;
short		movieRefNum;
short		resID = 0;
Str255		name;
Boolean	changed;

err = NewMovieFromFile( &theMovie, movieRefNum, &resID, name, 
											newMovieActive, &changed );

The parameter list to NewMovieFromFile() was described in detail last month. Here's a brief recap. The first argument, theMovie, holds a pointer to the memory that contains the movie data. The second argument, movieRefNum, is the reference number returned by the call to OpenMovieFile(). The third argument, resID, is the resource ID of the movie's moov resource (use 0 if a file holds a single movie, as is typically the case). The fourth argument, name, gets filled in with the name of the moov resource (this resource is often unnamed, in which case nil is returned). The fifth argument, newMovieActive, is an Apple-defined constant that specifies that the newly created movie be active (ready to play). Finally, the sixth argument, changed, indicates whether or not the Movie Toolbox needed to alter any data as it loaded movie data to memory (it shouldn't have to).

Your program now has the movie data in memory, so the movie file can be closed:

CloseMovieFile( movieRefNum );

Displaying a Movie in a Window (or Dialog Box)

Last month you saw how to display a movie and a movie controller in a window. Here we'll simply display a movie in a window (or a dialog box - the process is similar). First, open the window or dialog box:

WindowPtr	theWindow;

theWindow = GetNewCWindow( kWINDResID, nil, (WindowPtr)-1L );

Next, set the movie's display coordinate system to that of the window or dialog box in which the movie is to be played. As you saw last month, a call to the Movie Toolbox function SetMovieGWorld() sets the display coordinate system of the movie named in the first argument to that of the window named in the second argument:

SetMovieGWorld( theMovie, (CGrafPtr)theWindow, nil );

Next, get the dimensions of the movie in order to resize the window (or in order to appropriately place the movie in a dialog box that's larger than the movie). A call to the Movie Toolbox function GetMovieBox() provides that information in the form of a rectangle that holds the dimensions of a movie:

Rect		box;

GetMovieBox( theMovie, &box );

The left and top coordinates in the rectangle returned by GetMovieBox() may each be 0, in which case the right and bottom coordinates reveal the movies width and height, respectively. However, the left and top coordinates might not each be 0. So it's wise to make a call to OffsetRect() to force those two coordinates to 0:

OffsetRect( &box, -box.left, -box.top );

Now call the Movie Toolbox function SetMovieBox() to make the new, offset values the boundaries for the rectangle that defines the size of the movie:

SetMovieBox( theMovie, &box );

If you want the window that's to display the movie to be the exact size of the movie, then now's the time to resize that window - just call SizeWindow() using the right and bottom coordinates of rectangle box as the width and height of the window. In our example program we won't do that. Instead, we'll further adjust the coordinates of box to position the movie in a dialog box that's larger than the movie.

Playing a Movie Without a Movie Controller

If you want to play a movie automatically after the movie is displayed, or if you want to implement your own method of letting the user play a movie (as in displaying a standard push button in a dialog box), then you'll forego the movie controller code discussed in last month's article. Instead, you'll make use of a few Movie Toolbox functions designed for just this type of movie playing.

When a movie is saved, it may or may not be saved with the first frame designated as the frame to start the movie at. Before playing a movie you'll want to "rewind" the movie by making a call to GoToBeginningOfMovie(). After that, the Movie Toolbox function StartMovie() is called to prepare the movie for playing.

GoToBeginningOfMovie( theMovie );

StartMovie( theMovie );

StartMovie() takes care of a few tasks such as setting the movie's playback rate, but this routine doesn't actually play the movie. To do that your program should repeatedly call the Movie Toolbox function MoviesTask(). A single call to MoviesTask() processes only a small part of a movie, updating the display of the movie by drawing a frame - that's why this function is called from within a loop. The Movie Toolbox function IsMovieDone() returns a value of true when the movie in question has completed, so this function can be used to determine when the loop should end.

do
{
	MoviesTask( theMovie, 0 );
}
while ( IsMovieDone( theMovie ) == false );

A single call to MoviesTask() is capable of servicing, or updating, more than one movie. The first argument is the movie to service. If more than one movie is open, pass a value of nil to specify that all open movies be updated. The second argument is the number of milliseconds the program is willing to give the Movie Toolbox for its task of servicing movies. This is the total amount of time to be spend updating the movie or movies specified in the first argument. Passing a value of 0 here tells the Movie Toolbox to service each active movie once.

When your program is finished with a movie it should call DisposeMovie() to release the memory occupied by the movie data:

DisposeMovie( theMovie );

MoreQT

This month's program is MoreQT. As we did last month, here again the example program isn't menu-driven. When run, MoreQT displays the dialog box shown in Figure 1. Clicking the Apollo button results in the display and playing of a movie of the Apollo liftoff - as shown in Figure 2. When the movie finishes, its last frame is left in the movie-viewing area. To clear that area and return it to its original light gray state, click the Clear button. To play a movie of the Venus space probe, click the Venus button. To quit the program, you of course click the Quit button.


Figure 1. The MoreQT dialog box.


Figure 2. The MoreQT program as a movie is playing.

Creating the MoreQT Resources

Start the project by creating a new folder named MoreQT in your CodeWarrior development folder. Launch ResEdit, then create a new resource file named MoreQT.rsrc. Specify that the MoreQT folder as the resource file's destination. The resource file will hold resources of the types shown in Figure 3.


Figure 3. The MoreQT resources.

ALRT 128 and DITL 128 resources are used to define the program's error-handling alert. There's a second dialog item list resource - DITL 129 - that's paired with the file's only DLOG resource. Figure 4 shows DLOG 129, while Figure 5 shows DITL 129.


Figure 4. The DLOG resource.


Figure 5. The DITL for the one dialog box.

As shown in Figure 3, there's one PICT resource. This picture is used to create the three-dimensional look of the movie-playing area in the program's dialog box. To create this picture, I first determined the pixel dimensions of one of the movies (the two movies are the same size) I then used my paint program to create a shaded area slightly larger than a movie. In Figure 5 you see that the DITL for the dialog box includes a picture item that displays this PICT.

When you run MoreQT you'll notice that the dialog box. has a light gray background. This shading is easily achieved in ResEdit. First, open the dialog box DLOG, then click the Custom radio button (refer to Figure 4). Next, click the Content box to display a palette of colors that are used to define the dialog box background. Choosing a color creates a dctb resource that's automatically added to the resource file (see Figure 3).

Creating the MoreQT Project

Start CodeWarrior and choose New Project from the File menu. Use the MacOS:C_C++:MacOS Toolbox:MacOS Toolbox Multi-Target project stationary for the new project. You earlier created a project folder, so uncheck the Create Folder check box before clicking the OK button. Name the project MoreQT.mcp, and make sure the project's destination is the MoreQT folder.

Add the MoreQT.rsrc resource file to the new project. Remove the SillyBalls.rsrc file. You may also remove the ANSI Libraries folder from the project window if you want - the project doesn't use any of these libraries.

If you intend on making a PowerPC version (or fat version) of the program, you'll want to be sure to add the QuickTimeLib library to the PowerPC targets of your project. Choose Add File from the Project menu and work your way to this library. You'll find it in the Metrowerks CodeWarrior: MacOS Support: Libraries: MacOS Common folder (if it's not there, search your hard drive for it). When you add the library to the project CodeWarrior will display a dialog box asking you which targets to add the library to. Check the two PPC targets.

Create a new source code window by choosing New from the File menu.. Save the window, giving it the name MoreQT.c. Now choose Add Window from the Project menu to add this empty file to the project. Remove the SillyBalls.c placeholder file from the project window. You're all set to type in the source code.

To save yourself a bit of typing, go to MacTech's ftp site at ftp://ftp.mactech.com/src/mactech/volume15_1999/15.12.sit. There you'll find the MoreQT source code file available for downloading.

Walking Through the Source Code

MoreQT.c starts with several constants. The constant kALRTResID defines the ID of the ALRT resource used to define the error-handling alert. Constant kDLOGResID defines the ID of the DLOG resource used for the dialog box that is to display the QuickTime movie. Constants kQuitButton, kClearButton, kApolloButton, kVenusButton, and kFrameItem each define an item in DITL 129 (refer back to Figure 5 to see the relationship between these constants and the items in the DITL). Constant kFramePictID is the resource ID of the picture used to create the movie-playing area picture. Constant kFramePixelSize is the pixel width of the frame of the frame picture. This value will be used in centering a movie within the movie-playing area. Finally, kApolloMovieName and kVenusMovieName are the constants that define the names of the two QuickTime movies that the program will use.

/********************* constants *********************/

#define		kALRTResID					128
#define		kDLOGResID					129
#define		kQuitButton				1
#define		kClearButton				2
#define		kApolloButton			3
#define		kVenusButton				4
#define		kFrameItem					5
#define		kFramePictID				128
#define		kFramePixelSize			4
#define		kApolloMovieName		"\pMovieApollo"
#define		kVenusMovieName			"\pMovieVenus"

MoreQT declares a couple of global variables. gDone is used to signal the end of the program. Variable gMovieDialog is a dialog pointer that simplifies access to the items in this movie-playing dialog box.

/****************** global variables *****************/

Boolean					gDone = false;
DialogPtr				gMovieDialog;

Next come the program's function prototypes.

/********************* functions *********************/

void		ToolBoxInit( void );
void		OpenDialog( void );
void		LoadAndRunMovie( Str255 movieName );
void		DoError( Str255 errorString );

As it did in last month's example (which also relied on QuickTime), the main() function of MoreQT begins with the declaration of two variables that are used in the determination of whether QuickTime is present and in the initialization of the Movie Toolbox. After the Toolbox is initialized and the QuickTime-related tests are made, the application-defined OpenDialog() function is called.

/********************** main *************************/

void		main( void )
{
	OSErr	err;
	long		result;

	ToolBoxInit();

	err = Gestalt( gestaltQuickTime, &result );
	if ( err != noErr )
		DoError( "\pQuickTime not present");

	err = EnterMovies(); 
	if ( err != noErr )
		DoError( "\pError initializing the Movie Toolbox" ); 

	OpenDialog();
}

ToolBoxInit() remains the same as previous versions.

/******************** ToolBoxInit ********************/

void		ToolBoxInit( void )
{
	InitGraf( &qd.thePort );
	InitFonts();
	InitWindows();
	InitMenus();
	TEInit();
	InitDialogs( nil );
	InitCursor();
}

OpenDialog() opens and controls a standard modal dialog box. If you've ever included a non-movable dialog box in any of your own programs, then most of the OpenDialog() code should look familiar. The routine begins with a handful of local variable declarations, then the dialog box is opened and displayed:

/******************** OpenDialog *********************/

void OpenDialog( void )
{
	short			item;
	short			type;  
	Handle			handle;       
	Rect				rect;   
	PicHandle	framePict;

	gMovieDialog = GetNewDialog( kDLOGResID, nil, 
														 (WindowPtr)-1L);
	ShowWindow( gMovieDialog );
	SetPort( gMovieDialog );

Next, OpenDialog() enters a loop that executes until the program ends. Each call to the Toolbox function ModalDialog() returns the item number of a clicked on item - if in fact the user did click on an item. This item number is then used in a switch statement to determine how the program should handle the mouse click.

	while ( gDone == false )
	{
		ModalDialog( nil, &item );

		switch ( item )
		{
			case kApolloButton:
				LoadAndRunMovie( kApolloMovieName );
				break;
			case kVenusButton:
				LoadAndRunMovie( kVenusMovieName );
				break;
			case kClearButton:
				GetDialogItem( gMovieDialog, kFrameItem, &type, 
											&handle, &rect ); 
				framePict = GetPicture( kFramePictID );
				DrawPicture( framePict, &rect );
				break;
			case kQuitButton:
				gDone = true;
				break;
		}
	}
	DisposeDialog( gMovieDialog ); 
}

A click on the Apollo or Venus button results in the application-defined function LoadAndRunMovie() playing of the appropriate QuickTime movie. A click on the Clear button results in the displaying of the PICT resource in order to obscure the movie-playing area (which will be displaying the last frame of the most recently played movie). The call to GetDialogItem() is made to obtain the boundaries of the dialog item that holds the picture. A call to GetPicture() loads the picture to memory, and a call to DrawPicture() draws the picture at the location held in the rectangle rect. A click on the Quit button ends the program.

When the user clicks on either the Apollo or Venus button, LoadAndRunMovie() is called. The name of the movie is passed to this function, and LoadAndRunMovie() then does just that - it loads to memory the appropriate movie, then plays the movie once. Almost all of the code in LoadAndRunMovie() was introduced earlier in this article. The function starts with a slew of local variable declarations:

/****************** LoadAndRunMovie ******************/

void LoadAndRunMovie( Str255 movieName )
{
	OSErr		err;
	FSSpec		theFSSpec;
	short		fileRefNum;
	Movie		theMovie;
	short		movieResID = 0;  
	Str255		movieResName;
	Boolean	altered;
	Rect			box;
	short		type;  
	Handle		handle;       
	Rect			rect;   

A call to FSMakeSpec() creates a file system specification for the appropriate movie. That FSSpec is then used in a call to OpenMovieFile(). After the movie file is opened, NewMovieFromFile() loads the file's movie data to memory. We're then finished with the movie file, so it can be closed:

	err = FSMakeFSSpec( 0, 0, movieName, &theFSSpec );
	err = OpenMovieFile( &theFSSpec, &fileRefNum, 					fsRdPerm );
	err = NewMovieFromFile( &theMovie, fileRefNum, 					&movieResID,
             movieResName, newMovieActive, 
												&altered );
	CloseMovieFile( fileRefNum );

Earlier in this article you saw how SetMovieGWorld() matches the display coordinate system of a movie to a window. Here the same routine is used to pair a movie to a dialog box:

	SetMovieGWorld( theMovie, (CGrafPtr)gMovieDialog, nil); 

As discussed earlier in this article, GetMovieBox() and OffsetRect() are used to get the bounding rectangle of the a movie and to then offset the boundaries to (0, 0):

	GetMovieBox( theMovie, &box );
	OffsetRect( &box, -box.left, -box.top );

Here, rather than now setting the new boundaries to the movie, we first reposition the rectangle so that it is centered in the movie-playing area of the dialog box. The boundaries of the movie-playing area are defined the picture item in the dialog box. A call to GetDialogItem() gets that picture's boundaries. A call to OffsetRect() shifts the movie's current boundary rectangle so that its top and left sides match the coordinates of the picture - with the addition of a few pixels to account for the "frame-like" shading we've given to the picture (see Figure 3). Now we've finally got the movie's coordinates established, so a call to SetMovieBox() can be made to lock in these values to the movie:

	GetDialogItem( gMovieDialog, kFrameItem, 
         &type, &handle, &rect ); 
	OffsetRect( &box, rect.left + kFramePixelSize, 
							rect.top + kFramePixelSize );
	SetMovieBox( theMovie, &box );

Now it's time to play, then dispose of, the movie. The following code is unchanged from the discussion earlier in this article.

	GoToBeginningOfMovie( theMovie );

	StartMovie( theMovie );

	do
	{
		MoviesTask(theMovie, 0);
	}
	while ( IsMovieDone( theMovie ) == false );

	DisposeMovie( theMovie );
}

DoError() is unchanged from prior versions. A call to this function results in the posting of an alert that holds an error message. After the alert is dismissed the program ends.

/********************** DoError **********************/

void		DoError( Str255 errorString )
{
	ParamText( errorString, "\p", "\p", "\p" );

	StopAlert( kALRTResID, nil );

	ExitToShell();
}

Running MoreQT

Run MoreQT by selecting Run from CodeWarrior's Project menu. After compiling the code and building a program, CodeWarrior runs the program. The dialog box will appear. Go ahead and play the movies as often as you wish. In between movies, click the Clear button to verify that it does in fact clear_the movie-playing area. When finished, click the Quit button.

Till Next Month...

Last month we introduced QuickTime and movie controllers. This month we carried on with our study of adding movie playing capabilities to a program. Study and experiment with the code from both last month's and this month's projects. You'll want to get well grounded in QuickTime basics - with the powerful and cross-platform capabilities of QuickTime 4, Apple is demonstrating the QuickTime is going to be a key technology for Mac programmers to understand...

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Apple iTunes 12.2 - Play Apple Music...
Apple iTunes lets you organize and stream Apple Music, download and watch video and listen to Podcasts. It can automatically download new music, app, and book purchases across all your devices and... Read more
Apple Security Update 2015-005 - For OS...
Apple Security Update 2015-005 is recommended for all users and improves the security of OS X. For detailed information about the security content of this update, please visit: http://support.apple.... Read more
Apple HP Printer Drivers 3.1 - For OS X...
Apple HP Printer Drivers includes the latest HP printing and scanning software for OS X Lion or later. For information about supported printer models, see this page. Version 3.1: The latest printing... Read more
Epson Printer Drivers 3.1 - For OS X 10....
Epson Printer Drivers installs the latest software for your EPSON printer or scanner for OS X Yosemite, OS X Mavericks, OS X Mountain Lion, and OS X Lion. For more information about printing and... Read more
Xcode 6.4 - Integrated development envir...
Xcode provides everything developers need to create great applications for Mac, iPhone, and iPad. Xcode brings user interface design, coding, testing, and debugging into a united workflow. The Xcode... Read more
OS X Yosemite 10.10.4 - Apple's lat...
OS X Yosemite is Apple's newest operating system for Mac. An elegant design that feels entirely fresh, yet inherently familiar. The apps you use every day, enhanced with new features. And a... Read more
Dash 3.0.2 - 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
FontExplorer X Pro 5.0 - Font management...
FontExplorer X Pro is optimized for professional use; it's the solution that gives you the power you need to manage all your fonts. Now you can more easily manage, activate and organize your... Read more
Typinator 6.6 - Speedy and reliable text...
Typinator turbo-charges your typing productivity. Type a little. Typinator does the rest. We've all faced projects that require repetitive typing tasks. With Typinator, you can store commonly used... Read more
Arq 4.12.1 - Online backup to Google Dri...
Arq is super-easy online backup for the Mac. Back up to your own Google Drive storage (15GB free storage), your own Amazon Glacier ($.01/GB per month storage) or S3, or any SFTP server. Arq backs up... Read more

Hands-On With Raceline CC
Set for release soon, Rebellion’s motorbike racing game, Raceline CC certainly looks stylish. But how does it play? I got my hands on a preview build to answer exactly that. | Read more »
Siegefall - Tips, Tricks, and Strategies...
So, you fancy establishing a base and ruling the world again. Siegefall is a convenient place to do that, but how about some great tips and tricks on how best to go about it? Here are a few ideas on how to get ahead as a beginner to this medieval... | Read more »
The WWE Comes to Racing Rivals - Because...
Racing Rivals is a racing game that's all about, well, rivalry. And who knows rivalry better than WWE superstars (shhhh, that was rhetorical)? [Read more] | Read more »
Hey, Who Put Apple Music in My SoundHoun...
One of the App Store's popular music discovery sources - SoundHound - has already been updated to include Apple's own music discovery source - Apple Music. That was fast! [Read more] | Read more »
Arcane Legends has a New Expansion Calle...
Arcane Legends has been going strong since it debuted at the tail end of 2012. So well, in fact, that it's already up to its sixth expansion. [Read more] | Read more »
Vector 2 is Officially a Thing and it...
Vector is a pretty cool parkour-driven runner that's gotten a pretty decent following since it first came out - although personally I think more people could stand to show it some love. Anyway, Nekki has announced that a sequel isofficially on its... | Read more »
Get Ready to Trucksform and Roll Out (an...
It looks like NuOxygen is bringing the truck-transforming racer Trucksform (get it?) to iOS in a couple of weeks. Although really it's more of an auto-driver than a racer. But still, transforming trucks! [Read more] | Read more »
This Week at 148Apps:June 22-26, 2015
June's Summer Journey Continues With 148Apps How do you know what apps are worth your time and money? Just look to the review team at 148Apps. We sort through the chaos and find the apps you're looking for. The ones we love become Editor’s Choice,... | Read more »
LEGO® Minifigures Online (Games)
LEGO® Minifigures Online 1.0.1 Device: iOS iPhone Category: Games Price: $4.99, Version: 1.0.1 (iTunes) Description: | Read more »
World of Tanks Blitz celebrates its firs...
Today marks the first anniversary of the launch of World of Tanks Blitz, the mobile version of the PC tank battler, World of Tanks. World of Tanks Blitz launched on iOS and Android on June 26th last year and to celebrate, Wargaming is giving all... | Read more »

Price Scanner via MacPrices.net

Apple Releases OS X 10.10.4 With WIFi Fix, iO...
On Tuesday, Apple released final versions of OS X 10.10.4 and iOS 8.4, as well as updates for the Safari browser for OS X Yosemite, Mavericks, and Mountain Lion. The OS X 10.10.4 update focuses on... Read more
Dual-Band High-Gain Antennas for Home Wi-Fi N...
Linksys has announced what it claims are the first dual-band, omni-directional high-gain antennas for the consumer market. The new Linksys high-gain antennas available in a 2- and 4-pack (WRT004ANT... Read more
Apple refurbished 2014 15-inch Retina MacBook...
The Apple Store has Apple Certified Refurbished 2014 15″ 2.2GHz Retina MacBook Pros available for $1609, $390 off original MSRP. Apple’s one-year warranty is included, and shipping is free. They have... Read more
Clearance 2014 MacBook Airs available for up...
Adorama has 2014 MacBook Airs on sale for up to $301 off original MSRP including NY + NJ sales tax and free shipping: - 11″ 256GB MacBook Air: $798 $301 off original MSRP - 13″ 128GB MacBook Air: $... Read more
5K iMacs on sale for $100 off MSRP, free ship...
B&H Photo has the new 27″ 3.3GHz 5K iMac on sale for $1899.99 including free shipping plus NY tax only. Their price is $100 off MSRP. They have the 27″ 3.5GHz 5K iMac on sale for $2199, also $100... Read more
27-inch 3.2GHz iMac on sale for $1679, save $...
B&H Photo has the 27″ 3.2GHz iMac on sale for $1679.99 including free shipping plus NY sales tax only. Their price is $120 off MSRP. Read more
12-inch 1.2GHz Gray MacBook on sale for $1487...
Amazon.com has the new 12″ 1.2GHz Gray MacBook in stock and on sale for $1487 including free shipping. Their price is $102 off MSRP, and it’s the lowest price available for this model. We expect... Read more
15-inch 2.2GHz Retina MacBook Pro on sale for...
Amazon.com has the 15″ 2.2GHz Retina MacBook Pro on sale for $1819 including free shipping. Their price is $180 off MSRP, and it’s the lowest price available for this model. Read more
OtterBox Releases New Symmetry Series Metalli...
Otterbox’s new Symmetry Series of smartphone cases flaunts the best of both both street style and street smarts with their new metallic finishes and trusted OtterBox protection for iPhone 6 and... Read more
Eliminate Cable Chaos with New GE Branded Wra...
GE licensee Jasco Products has introduced a new line of GE branded Wrap-n-Charge USB wall chargers with built-in cable management. “We are always working to combine great technology with innovative... Read more

Jobs Board

*Apple* TV Live Streaming Frameworks Test En...
**Job Summary** Work and contribute towards the engineering of Apple 's state-of-the-art products involving video, audio, and graphics in Interactive Media Group (IMG) at Read more
Project Manager, WW *Apple* Fulfillment Ope...
…a senior project manager / business analyst to work within our Worldwide Apple Fulfillment Operations and the Business Process Re-engineering team. This role will work Read more
Senior Data Scientist, *Apple* Retail - Onl...
**Job Summary** Apple Retail - Online sells Apple products to customers around the world. In addition to selling Apple products with unique services such as iPad Read more
*Apple* Music Producer - Apple (United State...
**Job Summary** Apple Music seeks a Producer to help shepherd some of the most important content and editorial initiatives within the music app, with a particular focus Read more
Sr. Technical Services Consultant, *Apple*...
**Job Summary** Apple Professional Services (APS) has an opening for a senior technical position that contributes to Apple 's efforts for strategic and transactional Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.