TweetFollow Us on Twitter

Feb 99 Getting Started

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

Sound Basics

by Dan Parks Sydow

How a Mac program plays sounds stored in resources and files

In October and December of this past year, Getting Started covered animation. The movement of objects in a window is one very important aspect of bringing multimedia effects into your Mac program. Another key element to making multimedia a reality is the playing of sounds. This month we'll take a look at how to easily add sound-playing capabilities to any of your own Macintosh applications. To give you a choice of techniques, we'll cover the playing of sounds that are stored in an application's resource fork, and the playing of sounds that are kept in separate sound files.

The Sound Manager

The standard audio hardware on Macintosh computers includes one or more internal speakers. A Mac program includes the code that specifies what sound to play, and the hardware generates the sound itself. The Sound Manager holds the code that translates your wishes to information the hardware can use. The Sound Manager 3.0 software is built into the system of every PowerPC-based Mac, came as an extension included with many pre-Mac OS 8 versions of the Macintosh operating system, and is available as a system extension for older Macs or Macs running an older version of the system software.

The Mac has always been able to generate sound, but it hasn't always had the Sound Manager to serve as the programmer's link to the Mac's speakers. Prior to System 6.0, the sound routines were a part of the Toolbox but weren't specifically organized into what we now know as the Sound Manager. Version 2.0, or the enhanced Sound Manager, was introduced along with System 6.0.7. Version 3.0 became a part of System 7.5. A Macintosh owner who hasn't upgraded to System 7.5 or beyond can gain the capabilities of Sound Manager 3.0 by adding the Sound Manager system software extension to his System Folder.

Sound Manager 3.0 improves upon how the Mac works with sound, and adds new sound-playing capabilities to the Macintosh - so your sound-playing program will want to make use of it. Most Mac owners now have Sound Manager 3.0 as a part of their system software - but a few users may not. You'll want to save the user of an older Mac (or older system software) the aggravation of crashing their computer by checking for the presence of version 3.0 (or later) of the Sound Manager before your application calls Sound Manager Toolbox routines.

The check for a particular version of the Sound Manager involves the use of a variable of type NumVersion. Here's the definition of the NumVersion data type:

struct NumVersion
   UInt8   majorRev;
   UInt8   minorAndBugRev;
   UInt8   stage;
   UInt8   nonRelRev;

Apple defines the Byte type to be an unsigned char, so it's range is 0 to 255. Simply as a convenience, Apple defines the UInt8 type to be the same as the Byte type. By the type name it should be readily apparent that a UInt8 variable is an unsigned integer occupying eight bits, or one byte. When a Toolbox routine returns a NumVersion, you can check the majorRev field to see if the version is appropriate to meet your program's requirements. In the case of the check for Sound Manager 3.0, call the Toolbox routine SndSoundManagerVersion() and then see if the majorRev field of the returned NumVersion has a value of at least 3:

NumVersion      theSndMgrVersion;

theSndMgrVersion = SndSoundManagerVersion();
if ( theSndMgrVersion.majorRev < 3 )
   // user has an outdated version of the Sound Manager

Sound Resources

Apple has created the snd resource type to hold the data for a sound. It's very important to note that all resource types must be four characters, and that the sound resource type is somewhat unusual in that it ends with a space. If your code includes a reference to the sound resource type and you omit the trailing space character, the code won't compile. A sound can exist as a sound resource or as a sound file (we look at sound files a bit later). Storing a sound as a resource in your application's resource fork is a good way to ensure that the sound will always be available for your application's use.

The Toolbox function SndPlay() is used to play a sound resource. SndPlay() expects a sound resource to already be loaded into memory, so you'll want to call GetResource() before calling SndPlay(). Pass GetResource() the type of resource you're interested in (here, a snd resource) and the ID of the resource, and GetResource() loads the specified resource and returns a handle to the memory location of the loaded data. Assuming your program has a snd resource with an ID of 12000, here's how the call to GetResource() looks:

Handle      theHandle;

theHandle = GetResource( 'snd ', 12000 );

Once you have a handle to a sound resource, call SndPlay() to play the sound. Here's a typical call to this routine:

SndPlay( nil, (SndListHandle)theHandle, false );

The first of the three SndPlay() parameters is a pointer to a sound channel. The Sound Manager always uses a sound channel to store information about how a sound is to be played. If you pass a value of nil as this first parameter, the Sound Manager takes care of the allocation of a sound channel. The second parameter is a handle to the sound resource to play. GetResource() returned a generic handle, while SndPlay() requires a specific type of handle - a SndListHandle. Typecasting the generic handle is all that's necessary. The last parameter to SndPlay() is a Boolean value that indicates whether the sound should be played asynchronously (true) or synchronously (false).

With asynchronous sound-playing, other actions can take place at the same time as the playing of the sound. With synchronous sound playing, no other actions take place until the sound has finished playing. The above call to SndPlay() plays the sound synchronously. To play a sound asynchronously, you need to allocate your own sound channel and you need to know about a special type of routine called a callback procedure. Both these topics are beyond the scope of this article - but watch for them next month.

Sound Files

If you'd rather your program play a sound from a separate file, the Toolbox makes that possible. Sound resources are handy because the sounds are kept within the application that plays them, but there are situations when you'll want to instead store sounds in separate files. A sound used by more than one application would be a good candidate to be stored in a file. A large sound is also a good nominee to be stored in a file rather than a resource. This is because Apple recommends that a sound resource be kept to less than half a megabyte in size, while no such limit is imposed on a sound file.

Sounds can be stored in several types of files, but on the Mac you'll work primarily with sound files of the formats AIFF (Audio Interchange File Format) and AIFF-C (Audio Interchange File Format Extension for Compression). The Toolbox makes playing AIFF and AIFF-C sound files easy, but before the sound within a file can be played your application needs to find the file on disk and open it. An example of gathering file information for a sound file and then opening that file's data fork (because the sound data in an AIFF or AIFF-C file is held in that fork) is shown here:

FSSpec      theFSSpec;
OSErr      theErr;
short      fileRefNum;
FSMakeFSSpec( 0, 0, "\pMySoundFile", &theFSSpec );
FSpOpenDF( &theFSSpec, fsRdPerm, &fileRefNum );

A file system specification, represented by a variable of the data structure type FSSpec, holds information about the disk location, or path, of a single file. Given a file name and a pointer to an FSSpec variable, the File Manager routine FSMakeFSSpec() fills in the fields that make up the FSSpec. The first two parameters to FSMakeFSSpec() specify the volume (or disk) the file resides on and the directory (folder) the file is in. Passing a value of 0 for each of these parameters tells FSMakeFSSpec() that the named file is in the same directory as the application.

The File Manager routine FSpOpenDF() opens a file's data fork. As shown above, FSpOpenDF() requires three parameters. The first is a pointer to a previously filled-in FSSpec. The second parameter is a permission level. Using the Apple-defined constant fsRdPerm here tells the File Manager to open the file with read permission only: the file data can be read, but the application that opens the file cannot write to (alter) it. The last parameter is a pointer to a variable that is to serve as a file reference number. After opening the specified file, the File Manager creates a reference number for the file and places that value in this last parameter.

To play an opened sound file, use the Toolbox function SndStartFilePlay(). Here's an example of the use of this function:

SndStartFilePlay( nil, fileRefNum, 0, 40960, nil, nil, 
                         nil, false );

The eight parameters make the use of SndStartFilePlay() seem difficult, but in fact it's easy to use. That's because most of the parameters can be set to nil. Let's take a quick look at each parameter:

  • The first parameter to SndStartFilePlay() is a pointer to a sound channel. As with SndPlay(), pass a nil pointer to let the Sound Manager allocate the sound channel.
  • The second parameter is a reference number to an already open AIFF or AIFF-C File. This is the reference number returned by the prior call to FSpOpenDF().
  • The third parameter specifies whether SndStartFilePlay() will be playing a sound file or a sound resource. SndStartFilePlay() can be used to play sound resources, though Apple recommends you use SndPlay() instead. A value of 0 specifies that a sound file is to be used.
  • The fourth parameter designates the size of an input buffer (a block of free bytes of memory) that the Sound Manager can use in the playing of the sound file. SndStartFilePlay() works by reading in some of the sound data from a sound file, playing the sound defined by that data, and then reading in additional sound file data. For successful sound play Apple recommends a buffer size of at least 20,480 (20 K) bytes. The above snippet doubles that minimum recommended value to 40,960 (40 K) bytes.
  • The fifth parameter allocates the input buffer (the fourth parameter only established this buffer's size). Pass a nil pointer here to let the Sound Manager handle the buffer allocation.
  • The sixth parameter specifies whether SndStartFilePlay() should play a part, or all, of a sound file's sound data. Pass a nil pointer here to play the entire sound.
  • The seventh parameter is a pointer to a completion routine - a function used for asynchronous sound playing (performing other actions while a sound plays). For synchronous play (playing a sound without other actions, as described in this article), pass a nil pointer.
  • The eighth parameter indicates whether the sound is to be played asynchronously (true) or synchronously (false).

The SndStartFilePlay() function will be supported in the upcoming Carbon API, but Apple will be encouraging developers to start relying on QuickTime for the handling of a variety of multimedia files. Look to future issues of MacTech Magazine for QuickTime coverage. See last month's Getting Started column for an introduction to Carbon.

Obtaining Sounds

If your program is to play sounds, you'll of course need to obtain those sounds from somewhere. Sounds can be obtained from a number of sources. If you subscribe to an online service such as America Online or CompuServe, check their own software libraries for free sound files. If you need a greater variety of sounds, invest a small amount (about 30 bucks will do it) for a commercial product - a CD-ROM that holds hundreds, or more likely, thousands, of sounds in a number of formats. If the sound you seek is unique, consider creating it yourself using your Mac's built-in microphone or by plugging a sound digitizer into the back of your Macintosh.

Mac users often find sounds distributed as Finder sound files - also referred to as System 7 sound files. You'll recognize such a sound file by its icon - it looks like a document with a speaker on it. A Finder sound file is so named because it can be played from the Finder - just double-click on its icon on the desktop to hear the sound. A Finder sound file stores a sound as a snd resource, so if your program plays sound resources, you can make use of a Finder sound file's sound by opening the file from a resource editor, copying the file's snd resource, and pasting that resource into your project's resource file.

Often the same sound will be offered in a few formats, such as a Finder sound file and an AIFF file. Sometimes a sound will be distributed in just one format. If the sound of interest isn't in the format you want, use a sound-converting program to change its format. The freeware program SoundApp is an example of such a utility - you can find it on the Web at just about any archive of Mac software (such as at With a sound-converting program you can change an AIFF to a Finder sound file and then use a resource editor to copy that converted file's snd resource to your project's resource file. Alternatively, you can convert a Finder sound file to an AIFF file and then store that file with your application. In either case, for your program to play the sound you'll of course need to include the appropriate sound-playing code in your project's source code file.


This month's program is called SoundPlayer. Running SoundPlayer results in the appearance of the menu bar shown in Figure 1. The menu of significance is the Sound menu. Choosing either of the items in this menu results in the playing of the corresponding sound. As you can surmise from the menu item names, the cat meow sound is stored in the SoundPlayer's resource fork, while the dog bark sound exists as a separate sound file that needs to be present in the same folder as the SoundPlayer application. After playing the sounds as often as desired, choose Quit from the File menu to end the program.

Figure 1. The SoundPlayer menu.

Creating the SoundPlayer Resources

To begin, open your CodeWarrior development folder and create a folder named SoundPlayer. Start up ResEdit and create a new resource file named SoundPlayer.rsrc inside the SoundPlayer folder. Figure 2 shows the five types of resources used by SoundPlayer. With the exception of the snd resource, the resource types should look familiar to you.

Figure 2. The SoundPlayer resources.

SoundPlayer uses the same ALRT resource and DITL resource that have been used in the last several Getting Started examples. These two resources are used to support the error-handling alert displayed by the program's DoError() routine. Figure 3 shows the four MENU resources the program needs. The items in the Sound menu include (resource) and (file) in their names so that you'll be able to tell which item uses which type of sound - in a real-world application there's no need to relay this information to the user. After creating the MENU resources, create an MBAR resource that references all four menus. That is, make sure it includes IDs 128, 129, 130, and 131.

Figure 3. The SoundPlayer menu resources.

The snd resource used by SoundPlayer isn't a resource you can create in ResEdit. ResEdit isn't a sound editor, so to get the sound you need you'll have to rely on a sound-producing or sound-editing software program. Or, pick up a sound resource by following one of the suggestions made earlier in this column. This month's project is available for download from MacTech's ftp site at, and it includes a single system sound file named CatMeow. You can use ResEdit to open that file, copy its one snd resource, and then paste that resource into the SoundPlayer.rsrc file.

Figure 4 shows how the CatMeow file looks when opened in ResEdit. Here you see what happens when you double-click on the snd icon and then double-click on a particular snd resource. ResEdit is composed of a number of editors, but there is no sound editor. So ResEdit opens the sound resource in a hex editor window that does nothing but show the raw data that makes up the digital sound. After satisfying your curiosity, close the hex editor. Then click on the CatMeow resource in the list of snd resources, copy it, and paste it into the SoundPlayer.rsrc file.

Figure 4. The sound resource in a system sound file.

That's it for the SoundPlayer.rsrc file. Save the file and quit ResEdit - it's time to get started on the project file.

Creating the SoundPlayer Project

Launch CodeWarrior and choose New Project from the File menu to create a new project based on the MacOS:C_C++:MacOS Toolbox:MacOS Toolbox Multi-Target stationary. Uncheck the Create Folder check box before clicking the OK button. Name the project SoundPlayer.mcp and make the SoundPlayer folder the project's destination.

Add the SoundPlayer.rsrc file to the project window and remove the SillyBalls.rsrc file. The SoundPlayer project doesn't use of any of the standard ANSI libraries, so you can feel free to remove the ANSI Libraries folder.

Choose New from the File menu to create a new, empty source code window. Save it with the name SoundPlayer.c and then choose Add Window from the Project menu to add the file to the project. Remove the SillyBalls.c file from the project window if you already haven't done so. The source code listing for the SoundPlayer program appears next in the source code walk-through. You can type the code into the SoundPlayer.c file as you read the walk-through, or you can save a little effort and download the entire SoundPlayer project from MacTech's ftp site at

Walking Through the Source Code

Now, the SoundPlayer code. SoundPlayer starts off with the usual constant definitions. Most of the constants have appeared in previous projects, but there are a couple of additions. The constant ksnd_ResMeowID is the resource ID of the project's one snd resource - the resource used when the user chooses Meow (resource) from the Sound menu. For sound resources, Apple reserves IDs up to 8191 - so always give your own resources of this type an ID greater than 8191. The constant kBarkFileName is a Pascal-style string that holds the name of the AIFF sound file that's to be used when the user chooses Bark (file) from the Sound menu.

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

#define   kMBARResID            128
#define   kALRTResID            128
#define   ksnd_ResMeowID        12000

#define   kBarkFileName      "\pDogBark.AIFF"

#define   kSleep                7
#define   kMoveToFront         (WindowPtr)-1L

#define   mApple                128
#define   iAbout                1

#define   mFile                 129
#define   iQuit                 1

#define   mSound                131
#define   iMeow                 1
#define   iBark                 2

SoundPlayer needs just one global variable - the now-familiar gDone. The user's quitting of the program toggles this variable's value from false to true.

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

Boolean      gDone;

Next come the program's function prototypes.

/********************* functions *********************/
void      ToolBoxInit( void );
void      MenuBarInit( void );
void      PlaySoundResource( void );
void      PlaySoundFile( void );
void      EventLoop( void );
void      DoEvent( EventRecord *eventPtr );
void      HandleMouseDown( EventRecord *eventPtr );
void      HandleMenuChoice( long menuChoice );
void      HandleAppleChoice( short item );
void      HandleFileChoice( short item );
void      HandleSoundChoice( short item );
void      DoError( Str255 errorString );

The main() function begins by initializing the Toolbox. After that a check is made to ensure that the user has version 3.0 or later of the Sound Manager. If that isn't the case, the application-defined routine DoError() posts a message and exits the program.

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

void      main( void )
   NumVersion theSndMgrVers;

   theSndMgrVers = SndSoundManagerVersion(); 
   if ( theSndMgrVers.majorRev < 3 )
       DoError( "\pSound Manager is outdated" );

The ToolBoxInit() and MenuBarInit() functions are the same as prior versions.

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

void      ToolBoxInit( void )
   InitGraf( &qd.thePort );
   InitDialogs( nil );

/******************** MenuBarInit ********************/

void      MenuBarInit( void )
   Handle            menuBar;
   MenuHandle      menu;
   menuBar = GetNewMBar( kMBARResID );
   SetMenuBar( menuBar );

   menu = GetMenuHandle( mApple );
   AppendResMenu( menu, 'DRVR' );

When the user chooses Meow (resource) from the Sound menu, it is the application-defined function PlaySoundResource() that handles the task of loading a sound resource into memory and playing the sound.

/****************** PlaySoundResource ****************/

void PlaySoundResource( void )
   Handle theHandle;
   OSErr theErr;
   theHandle = GetResource( 'snd ', ksnd_ResMeowID );
   if ( theHandle == nil )
      DoError( "\pAttempt to load sound resource failed" );

   HLock( theHandle );
   theErr = SndPlay( nil, (SndListHandle)theHandle, 
                               false );
   HUnlock( theHandle );

   if ( theErr != noErr )
      DoError( "\pPlaying of sound failed" );
   ReleaseResource( theHandle );

If the call to GetResource() successfully loads the sound resource, PlaySoundResource() then plays the sound. The calls to the Toolbox functions HLock() and HUnlock() force the system to leave the sound data untouched in memory. That is, during the duration of the execution of SndPlay(), the system can't move the memory referenced by the variable theHandle. That's important - you don't want the system moving the sound data in the middle of sound playing. In the SndPlay() snippet presented earlier in this article we didn't save the OSErr value returned by SndPlay(). Here we do. If SndPlay() fails to play the sound, an error will be returned and that fact can be relayed to the user. When sound playing is complete, the memory that's holding the sound resource data is released for future use by the program.

When the user chooses Bark (file) from the Sound menu, the application-defined function PlaySoundFile() gets called to open a sound file and play its sound. PlaySoundFile() begins by creating a file system specification for a file named DogBark.AIFF. Here we've set the volume and directory values of 0, so FSMakeFSSpec() expects the file named DogBark.AIFF to be in the same directory as the SoundPlayer application. If you want to keep sound files in a different directory, you'll need to study up on the FSSpec data structure in the Files volume of Inside Macintosh.

/******************** PlaySoundFile ******************/

void PlaySoundFile( void )
   FSSpec      barkFSSpec;
   OSErr      theErr;
   short      sndFileRefNum;
   theErr = FSMakeFSSpec( 0, 0, kBarkFileName, 
                                    &barkFSSpec );

If the creation of the FSSpec fails, the program ends. If the file system specification succeeds, it's time to open the file with a call to FSpOpenDF() and play its contents with a call to SndStartFilePlay().

   if ( theErr != noErr)
      DoError( "\pSound file not found" );

   theErr = FSpOpenDF( &barkFSSpec, fsRdPerm, 
                                  &sndFileRefNum );
   if ( theErr != noErr )
      DoError( "\pSound file opening error" );

   theErr = SndStartFilePlay( nil, sndFileRefNum, 0, 40960, 
                                          nil, nil, nil, false );
   if ( theErr != noErr )
      DoError( "\pSound file playing error" );

PlaySoundFile() includes plenty of error-handling code. Working with files on disk subjects the program to a number of potential problems, and we want to be ready for them. For instance, if the specified file is corrupt, the call to FSpOpenDF() may fail. If the file isn't a sound file, the call to SndStartFilePlay() would fail.

Now we're in the clear. The remaining SoundPlayer code is standard stuff that's necessary to keep our event-handling program running. The only additions exist to support a menu selection from the Sound menu.

/********************** EventLoop ********************/

void      EventLoop( void )
   EventRecord      event;
   gDone = false;
   while ( gDone == false )
      if ( WaitNextEvent( everyEvent, &event, kSleep, nil ) )
         DoEvent( &event );

/*********************** DoEvent *********************/

void      DoEvent( EventRecord *eventPtr )
   char      theChar;
   switch ( eventPtr->what )
      case mouseDown: 
         HandleMouseDown( eventPtr );
      case keyDown:
      case autoKey:
         theChar = eventPtr->message & charCodeMask;
         if ( (eventPtr->modifiers & cmdKey) != 0 ) 
            HandleMenuChoice( MenuKey( theChar ) );
      case updateEvt:
         BeginUpdate( (WindowPtr)(eventPtr->message) );
         EndUpdate( (WindowPtr)(eventPtr->message) );

/******************* HandleMouseDown *****************/

void      HandleMouseDown( EventRecord *eventPtr )
   WindowPtr   window;
   short         thePart;
   long            menuChoice;
   thePart = FindWindow( eventPtr->where, &window );
   switch ( thePart )
      case inMenuBar:
         menuChoice = MenuSelect( eventPtr->where );
         HandleMenuChoice( menuChoice );
      case inSysWindow : 
         SystemClick( eventPtr, window );

Here in HandleMenuChoice() we've added a switch case section for the handling of a selection from the Sound menu.

/******************* HandleMenuChoice ****************/

void      HandleMenuChoice( long menuChoice )
   short   menu;
   short   item;
   if ( menuChoice != 0 )
      menu = HiWord( menuChoice );
      item = LoWord( menuChoice );
      switch ( menu )
         case mApple:
            HandleAppleChoice( item );
         case mFile:
            HandleFileChoice( item );
         case mSound:
            HandleSoundChoice( item );
      HiliteMenu( 0 );

/****************** HandleAppleChoice ****************/

void      HandleAppleChoice( short item )
   MenuHandle      appleMenu;
   Str255            accName;
   short            accNumber;
   switch ( item )
      case iAbout:
         SysBeep( 10 );
         appleMenu = GetMenuHandle( mApple );
         GetMenuItemText( appleMenu, item, accName );
         accNumber = OpenDeskAcc( accName );

/******************* HandleFileChoice ****************/

void      HandleFileChoice( short item )
   switch ( item )
      case iQuit:
         gDone = true;

The HandleSoundChoice() routine is new to SoundPlayer. It's code should be intuitive - a Meow (resource) menu selection invokes PlaySoundResource() to play the sound resource, while a Bark (file) menu selection invokes PlaySoundFile() to play the DogBark.AIFF sound file.

/****************** HandleSoundChoice ****************/

void      HandleSoundChoice( short item )
   switch ( item )
      case iMeow:
      case iBark:

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

void      DoError( Str255 errorString )
   ParamText( errorString, "\p", "\p", "\p" );
   StopAlert( kALRTResID, nil );

Running SoundPlayer

Run SoundPlayer by selecting Run from the Project menu. Once your code compiles, the menu bar shown in Figure 1 appears. Choose one Sound menu item, then the other, to verify that the sounds play. Make sure your Mac's speaker volume is set above zero! Choose Quit from the File menu to end the animation and the program.

Till Next Month...

If your program will be playing more than one sound, you'll want to adapt either or both of the sound-playing routines to make them more flexible. In the case of PlaySoundResource(), you'll want to pass in the resource ID of the snd resource to play. For PlaySoundFile() you'll pass in the name of the sound file to play, or perhaps predetermine the file's FSSpec and pass in that data structure. Try adapting SoundPlayer so that the playing of a sound is contingent on something other than a menu selection. For instance, allow the user to click a button in a window to play a sound.

You can learn more about playing sounds by reading the Sound volume of Inside Macintosh. You can also wait until next month, when we look at how a Mac program plays asynchronous sound - sound that plays as other action takes place in the program. Asynchronous sound is an important way of playing sound because it doesn't tie up your program and force it to wait for sound-completion before carrying out other actions. This is especially important in games, where sound plays in the background, or accompanies some event (such as the sound of a gun firing, or a bomb exploding, or a rocket launching). Until next month's look at asynchronous sound, examine, modify, and play with the SoundPlayer code so that you're familiar with the basics of sound.


Community Search:
MacTech Search:

Software Updates via MacUpdate

BBEdit 11.6.5 - Powerful text and HTML e...
BBEdit is the leading professional HTML and text editor for the Mac. Specifically crafted in response to the needs of Web authors and software developers, this award-winning product provides a... Read more
OmniGraffle 7.3 - Create diagrams, flow...
OmniGraffle helps you draw beautiful diagrams, family trees, flow charts, org charts, layouts, and (mathematically speaking) any other directed or non-directed graphs. We've had people use Graffle to... Read more
OmniGraffle Pro 7.3 - Create diagrams, f...
OmniGraffle Pro helps you draw beautiful diagrams, family trees, flow charts, org charts, layouts, and (mathematically speaking) any other directed or non-directed graphs. We've had people use... Read more
DEVONthink Pro 2.9.11 - Knowledge base,...
DEVONthink Pro is your essential assistant for today's world, where almost everything is digital. From shopping receipts to important research papers, your life often fills your hard drive in the... Read more
DiskCatalogMaker 6.8.1 - Catalog your di...
DiskCatalogMaker is a simple disk management tool which catalogs disks. Simple, light-weight, and fast Finder-like intuitive look and feel Super-fast search algorithm Can compress catalog data for... Read more
Tunnelblick 3.7.0 - GUI for OpenVPN.
Tunnelblick is a free, open source graphic user interface for OpenVPN on OS X. It provides easy control of OpenVPN client and/or server connections. It comes as a ready-to-use application with all... Read more
Adobe Dreamweaver CC 2017 -...
Dreamweaver CC 2017 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 2017 allows you to... Read more
Adobe Animate CC 2017 16.2.0 - Advanced...
Animate CC 2017 is available as part of Adobe Creative Cloud for as little as $19.99/month (or $9.99/month if you're a previous Flash Professional customer). Animate CC 2017 (was Flash CC) lets you... Read more
A Better Finder Rename 10.15 - File, pho...
A Better Finder Rename is the most complete renaming solution available on the market today. That's why, since 1996, tens of thousands of hobbyists, professionals and businesses depend on A Better... Read more
Creative Kit 1.1 - $149.99
Creative Kit 2016--made exclusively for Mac users--is your ticket to the most amazing images you've ever created. With a variety of powerful tools at your fingertips, you'll not only repair and fine-... Read more

Royal Dungeon (Games)
Royal Dungeon 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: The king and his queen are trapped in their castle which suddenly turned out as a very dangerous place. The goal is to escape... | Read more »
Power Rangers: Legacy Wars beginner...
Rita Repulsa is back, but this time she's invading your mobile phone in Power Rangers: Legacy Wars. What looks to be a straightforward beat 'em up is actually a tough-as-nails multiplayer strategy game that requires some deft tactical maneuvering.... | Read more »
Hearthstone celebrates the upcoming Jour...
Hearthstone gets a new expansion, Journey to Un'Goro, in a little over a week, and they'll be welcoming the Year of the Mammoth, the next season, at the same time. There's a lot to be excited about, so Blizzard is celebrating in kind. Players will... | Read more »
4 smart and stylish puzzle games like Ty...
TypeShift launched a little over a week ago, offering some puzzling new challenges for word nerds equipped with an iOS device. Created by Zach Gage, the mind behind Spelltower, TypeShift boasts, like its predecessor, a sleak design and some very... | Read more »
The best deals on the App Store this wee...
Deals, deals, deals. We're all about a good bargain here on 148Apps, and luckily this was another fine week in App Store discounts. There's a big board game sale happening right now, and a few fine indies are still discounted through the weekend.... | Read more »
The best new games we played this week
It's been quite the week, but now that all of that business is out of the way, it's time to hunker down with some of the excellent games that were released over the past few days. There's a fair few to help you relax in your down time or if you're... | Read more »
Orphan Black: The Game (Games)
Orphan Black: The Game 1.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0 (iTunes) Description: Dive into a dark and twisted puzzle-adventure that retells the pivotal events of Orphan Black. | Read more »
The Elder Scrolls: Legends is now availa...
| Read more »
Ticket to Earth beginner's guide: H...
Robot Circus launched Ticket to Earth as part of the App Store's indie games event last week. If you're not quite digging the space operatics Mass Effect: Andromeda is serving up, you'll be pleased to know that there's a surprising alternative on... | Read more »
Leap to victory in Nexx Studios new plat...
You’re always a hop, skip, and a jump away from a fiery death in Temple Jump, a new platformer-cum-endless runner from Nexx Studio. It’s out now on both iOS and Android if you’re an adventurer seeking treasure in a crumbling, pixel-laden temple. | Read more »

Price Scanner via

Is Apple Planning An iPhone Based Modular Doc...
Today’s more powerful and larger-screened smartphones and phablets are becoming the default anchor computing device for more and more users computing devices, but even a five or six inch panel is not... Read more
Razer Launches New Razer Blade Pro World’s Fi...
Razer, the gaming and high performance hardware specialists, have announced the new Razer Blade Pro laptop — the first laptop to be qualified for THX Mobile Certification, an accreditation reserved... Read more
Gro CRM’s Apple Small Business Mac And iOS CR...
Gro Software, developers of the Mac CRM software for small business and enterprise, are included in FinancesOnline 2017 CRM Rising Stars and Great User Experience lists by business software review... Read more
Deal alert! 15-inch and 13-inch MacBook Pros...
B&H Photo has the new 2016 15″ and 13″ Apple MacBook Pros in stock today and on sale for up to $200 off MSRP. Shipping is free, and B&H charges NY sales tax only: - 15″ 2.7GHz Touch Bar... Read more
Save up to $420 on a new MacBook Pro with App...
Apple is offering Certified Refurbished 2016 15″ and 13″ MacBook Pros, including some Touch Bar models, for up to $420 off original MSRP. An Apple one-year warranty is included with each model, and... Read more
12-inch 1.2GHz Retina MacBooks on sale for $1...
B&H has 12″ 1.2GHz Retina MacBooks on sale for up to $200 off MSRP. Shipping is free, and B&H charges NY sales tax only: - 12″ 1.2GHz Space Gray Retina MacBook: $1449 $150 off MSRP - 12″ 1.... Read more
Is A New 10.5-inch iPad Still Coming In April...
There was no sign or mention of a long-rumored and much anticipated 10.5-inch iPad Pro in Apple’s product announcements last week. The exciting iPad news was release of an upgraded iPad Air with a... Read more
T-Mobile’s Premium Device Protection Now Incl...
Good news for T-Mobile customers who love their iPhones and iPads. The “Un-carrier” has become the first national wireless company to give customers AppleCare Services at zero additional cost as part... Read more
FileWave Ensures Support for Latest Apple OS...
FileWave multi-platform device management providers announced support for Apple’s release yesterday of iOS 10.3, macOS Sierra 10.12.4, and tvOS 11.2. FileWave has a history of providing zero-day... Read more
Use Apple’s Education discount to save up to...
Purchase a new Mac or iPad using Apple’s Education Store and take up to $300 off MSRP. All teachers, students, and staff of any educational institution qualify for the discount. Shipping is free: -... Read more

Jobs Board

Fulltime aan de slag als shopmanager in een h...
Ben jij helemaal gek van Apple -producten en vind je het helemaal super om fulltime shopmanager te zijn in een jonge en hippe elektronicazaak? Wil jij werken in Read more
Fulltime aan de slag als shopmanager in een h...
Ben jij helemaal gek van Apple -producten en vind je het helemaal super om fulltime shopmanager te zijn in een jonge en hippe elektronicazaak? Wil jij werken in Read more
Desktop Analyst - *Apple* Products - Montef...
…technology to improve patient care. JOB RESPONSIBILITIES: Provide day-to-day support for Apple Hardware and Software in the environment based on the team's support Read more
*Apple* Mobile Master - Best Buy (United Sta...
**493168BR** **Job Title:** Apple Mobile Master **Location Number:** 000827-Denton-Store **Job Description:** **What does a Best Buy Apple Mobile Master do?** At Read more
Fulltime aan de slag als shopmanager in een h...
Ben jij helemaal gek van Apple -producten en vind je het helemaal super om fulltime shopmanager te zijn in een jonge en hippe elektronicazaak? Wil jij werken in Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.