TweetFollow Us on Twitter

Client-Server Development

Volume Number: 14 (1998)
Issue Number: 11
Column Tag: Viewpoint

Client/Server Development based on the Apple Event Object Model

by Sascha Kratky and Christoph Reichenberger (UNI SOFTWARE PLUS)
Edited by Richard Clark

Using AEOM for the design and implementation of the VOODOO client/server system

The term "Client/Server System" has become one of most used terms in today's computing world. We use client applications practically every day to transfer incoming emails from mail servers, download files from FTP servers, or to browse HTML pages offered on web servers all over the world.

Developers have chosen the client/server architecture as a reasonable means to structure large software systems, in order to make them leaner, more efficient, and easier to maintain. The basis of every client/server system forms the protocol that the client and the server applications are using to communicate with each other. For some applications like file transfer, mail transfer or hypertext transfer, there are well-known standardized protocols (e. g. FTP, SMTP, or HTTP) which remove the burden of having to design a proprietary protocol from scratch. Other areas, such as software version control, lack standardized protocols.

This article deals with the design and implementation of a protocol for a client/server based software version control system. It starts with a discussion of the basic properties of client/server systems. It explains why we chose to design and implement the protocol for the VOODOO client/server system on top of the Apple Event Object Model. A section on the problems that the developer faces when implementing a client/server system on top of the Apple Event Object Model concludes the article.

Client/Server Systems

The term "Client/Server System" refers to a general software architecture which can be applied to a variety of different applications. Most discussions of client/server systems take for granted that we are aware of the advantages that arise from using a client/server-based system. It may be worthwhile to recall the encouragement that originally led to the widespread use of client/server systems. A main motivation for a client/server system is that it provides an elegant solution for applications that need concurrent access of many clients to the same data. This simultaneous access problem is sketched in Figure 1.

Figure 1. In a non client-server system, multiple clients may access the same resource concurrently.

In this scenario clients access a database concurrently on the file system level. The database is usually stored on a file server machine on the network and clients have to mount the database in order to access it. This results in the following shortcomings:

  • All clients make concurrent changes to parts of the database. To avoid modifying parts of the database that are currently in use by another client, the clients have to implement a file system-based locking mechanism. Nevertheless, an unexpectedly interupted client process may leave the database in an unstable state. The consequences are higher chances of database corruption and the loss of valuable data.
  • Every client application must have full knowledge of the external representation of the database. A change to this representation means that all client applications have to be upgraded as well.
  • Propagating changes one client has made to the database to the other clients currently working on the database is difficult and unreliable. Every client would have to constantly poll the files of the database for changes made by other users in the meanwhile.

Interestingly enough, many commercial systems that claim to be truly client-server-based still follow this "file-server" approach and therefore suffer from the previously-mentioned drawbacks.

In a real client/server-system the clients do not access the database directly but get the needed data by sending requests to a server application, which is the only process that directly accesses the database (Figure 2). Instead of mounting the remote database the clients connect to a server process running on a remote machine.

Figure 2. In a client-server system, a server mediates all accesses to the shared resource.

This avoids the above-mentioned shortcomings for the following reasons:

  • Only the server application makes changes to the files of the database. The server can schedule the incoming requests by the clients, such that the consistency of the data in the database is always assured. When a client process dies, the server can take care of undoing any unfinished transactions of that client.
  • Only the server process has to know the external representation of the database. Clients are unaffected by changes to the representation as long as the communication protocol remains unchanged.
  • The server can propagate changes from one client to the other clients, since it can keep track which client has retrieved what data and when this data has become obsolete.
  • The server can postpone housekeeping tasks until idle time, i. e. no client has sent a request to the server for some time. In VOODOO Server, the server uses delta storage to store all the versions space-efficiently. The server performs the calculation of these deltas during idle time, such that check-in operations for clients solely consist of transferring the file to the server.

These advantages make the client-server architecture well suited for the implementation of a true multi-user aware version control system where users can simultaneously check-in and check-out files.

Apple Events and the Apple Event Object Model

Apple events were introduced with System 7 as a means for applications to communicate with other applications in a standard way. Applications use Apple events to request information from other applications or to return information as result to these requests. An application can send an Apple event to another application on the same computer, an application on a remote computer, and even to itself.

The Apple Event Object Model (AEOM) enables developers to structure the scripting interface of their applications in an object-oriented way. The AEOM allows both the definitions of Apple events and Apple event Classes. The Apple event Classes are templates for Apple event Objects. Each object encapsulates some data that the user can access via the object's properties. Properties are named attributes of an object. For example, an object of class window would have its name, size, and position as properties.

Apple event objects can be hierarchically structured by making some Apple event objects elements of other objects. For example, an application object can have document objects as its elements. The documents themselves have window objects as elements. The resulting hierarchy of objects is called the containment hierarchy.

Apple events act on these objects just like messages do in objects oriented programs. Related classes and events can be grouped together into suites. The most commonly used objects and events are group together in the Apple event Core Suite. The Apple events defined in the Core Suite include Create Element, Delete, Get Data and Set Data. Just as a user can apply the Cut, Copy, and Paste commands to almost any data on the screen these commands should be implemented in virtually every Apple event object.

Apple events and Apple Event Objects also form the basis for the AppleScript programming language. AppleScript scripts enable the user to write down series of Apple events in a very high-level "natural" language. Users typically write scripts to automate everyday work or to combine the functionality of different applications to achieve a desired result. [Other applications, such as UserLand's Frontier can also generate Apple events to drive your application. - ed RC]

In order to be scriptable an application must contain an Apple Event Terminology Extension resource (a resource of type AETE), which defines the containment hierarchy as well as the mapping of objects and events to the vocabulary. AETE resources allow AppleScript to support multiple "dialects" such as English and Japanese.

The attempt to fully explain the Apple Event Object Model would be beyond the scope of this article. For more information on Apple events, the AEOM and AppleScript see Inside Macintosh: Inter-Application Communications and the AppleScript Language Guide.

Why should you use Apple events and the Apple Event Object Model?

Using Apple events and the Apple Event Object Model as the basis for a protocol has a number of advantages not only for clearness and extensibility reasons but also for your development and testing process:

  • Supporting the AEOM and Apple's Core Suite guarantees consistency with the scripting interface of other applications. When moving from one scriptable application to another the user will encounter already many familiar terms. So your server application is not only accessible for your clients but becomes a well-behaved citizen in the world of Open Scripting Architecture-compliant applications such as Frontier and FaceSpan.
  • You can test the server application by writing AppleScripts, which send Apple events to the server. Since you can save these scripts you are able to reproduce the same tests over and over again. These test scripts can grow into a handy test suite for your server application.
  • You can quickly build a GUI that accesses your server application using RAD tools like FaceSpan. Using FaceSpan you can implement an application completely in AppleScript while the FaceSpan environment offers Apple event classes for most user interface elements like Windows, Button and Lists. This makes it fairly easy to build a complete Mac-like client application with minimal effort on top of your AE-based client/server interface.
  • AEOM based protocols are quite flexible when it becomes necessary to extend the protocol. You can add a property to a class or add a completely new class which supports existing events. Rarely is it necessary to define a new Apple event, since many of the existing events can also act on objects of the new class. In contrast, protocols built without the Object Model often contain a myriad of verb-noun hybrid commands such as GetPreferences, SetPreferences, GetFolder, SetFolder, etc. The only way to extend such a protocol is by adding new Apple event definitions.
  • The transition from "procedural" Apple events to the AEOM can be compared with the transition from a procedural oriented language like C to an object oriented language like C++. This implies that many object oriented design methods like design patterns (1, 5) can also be applied to the design of your custom Apple Event Object Model making the design more flexible and easier to understand.

Designing your Custom AEOM

The following section guides you through the process of designing a client-server protocol based on the AEOM. We will use the protocol of our VOODOO Server application as an example here. Let us briefly explain VOODOO's functionality and data types in order to help you better understand the following description of the object hierarchy.

The VOODOO Server application is designed as an almost faceless server application, which exposes all its functionality through the Apple Event Object Model. Clients should be able to access all data stored in the server's database by sending requests to the server. Therefore, it was our goal that all elements of a VOODOO database should be modeled by means of Apple Event Objects. A VOODOO database holds collections of projects, parts and users. Users can log on to the server and open projects in the database. A project is further divided into different parts. A part represents a directory structure that is put under version control. Parts can also be shared among different projects. Figure 3 shows a VOODOO database for an example compiler project.

Figure 3. Structure of a VOODOO Server database.

The example database contains two projects: "Compiler" and "Linker". The project "Compiler" consists of the parts "Compiler" that stores all compiler specific files and a part "Toolslib" with common utility files. The part "Toolslib" is shared with the project "Linker", such that all changes made to "Toolslib" from the Compiler project are immediately visible in the project "Linker", too.

As mentioned, a part in the VOODOO database corresponds to a directory tree of the user's hard disk. The user can add files and folders to a part, fetch files from the part for modification and store a new versions to the database later. The VOODOO server takes care of storing different versions of files space efficiently using a combination of delta and compression algorithms. Each time a modification has been made to a part's item the server adds an event to the part's history. The event contains the date of the change, the user, the kind of change (e. g. added, revised, renamed, etc.), the items in the part that were changed and a comment. Besides that, the user can add a bookmark at an arbitrary point in time of the history to label milestones of the project.

It would be beyond the scope of this article to describe the full functionality of the VOODOO server. The server will form the basis for a new generation of version control tools to be released by UNI SOFTWARE PLUS in the near future but is also available for licensing to allow other companies to integrate version control functionality directly into their products. If you are interested in more details or want to download a free demo version, please visit <http://www.unisoft.co.at> or send an email to <voodoo@unisoft.co.at>.

Classes

The elements of a VOODOO database have been modeled as classes in the VOODOO suite. The inheritance hierarchy of these classes is sketched in Figure 4.

Figure 4. Inheritance hierarchy of the classes of the VOODOO AEOM.

All classes inherit from a common base class, which defines properties that are common to all the object classes. The directory tree of a part consists of files and folders. Therefore the base class of both is vItem, which represents a node in this tree. The part history contains both events and bookmarks. The common properties of these two classes have been extracted into a class entry which represents an entry in the part history.

Note that the names vItem, vFile, and vFolder were chosen to avoid name clashes with the terms item, file, folder which are the names of standard types in AppleScript.

The hierarchical relations of the objects can be seen in the containment hierarchy (Figure 5).

An object of class database forms the root of the containment hierarchy. The database contains user and project objects as elements. The recursive structure of directory trees is mirrored by the fact that the vFolder object can contain other vFolder objects.

Note that some object classes appear several times in the containment hierarchy. For example a vItem object contains all event objects that are valid for this item. This is a subset of the set of all the event objects that are valid for the whole part.

Figure 5. Containment hierarchy within the VOODOO AEOM.

Events

Once you have designed the inheritance and containment hierarchy for the classes, Apple event definitions can be added to your suite. Most of the events that you find you have to support are already defined in the Apple event Core Suite. As an example the following script shows how the Create Element event can be used to create files and folders in a part of the VOODOO database:

tell application "VOODOO Server"
   tell first database
      tell part "Compiler" of project "Compiler"
         make new vFolder at the end of it¨
            with properties {name:"FrontEnd"}
         make new vFile at the end of result¨
            with properties {name:"Scanner.c"}
      end tell
   end tell
end tell

To retrieve data from the database the Get Data and Count Elements Apple events can be used. The following script shows the use of these events.

tell application "VOODOO Server"
   tell project "Compiler" of first database
      - What parts does the project "Compiler" consist of?
      get name of every part
      tell part "Compiler"
- How many versions of the file "Scanner.c" have been stored?
         count every vVersion of vFile ¨
            "Scanner.c" in vFolder "FrontEnd"
      end tell
   end tell
end tell

When a user wants to store a new version of a file to a part, the data of this file has to be transferred to the server on the remote machine via Apple events. The following Apple events of the VOODOO Suite allow the transfer a particular version of a file to the database:

start store: announce a new store task
   start store  reference   - the vFile to be stored to
      [comment  string]     - comment describing new version
      [unlock  boolean]     - unlock vFile after store is finished (default:false)
   Result:   reference      - the newly created store task

The Apple event start store tells the server that the user wants to store data of a new version to a file. The comment parameter of the Apple event is used to initialize the comment of the event object that will be added to the part's history. The unlock parameter tells the server to unlock the file to be stored to, if the user previously locked it to prevent other users from making changes to it. The Apple event returns a reference to a store task as result, which is used later to store the actual data.

store: store data valid for the specified store task
   store  reference          - the store task the data is valid for
      data  anything         - the data block to be stored

The actual data of the version is transferred to the Server using one or several store Apple events (the data can be transferred in one block or in several chunks).

finish: finish the specified task
   finish  reference         - the task to finish

When all the data has been transferred to the server the client sends a finish Apple event to the store task to signal that the transfer is complete. The following example script illustrates the use of these Apple events:

tell application "VOODOO Server"
   tell first database
      tell part "Compiler" of project "Compiler"
         start store vFile "Scanner.c" in vFolder "FrontEnd"
         set theStoreTask to result
         store theStoreTask data "/* Scanner.c */"
         - store additional data ...
         finish theStoreTask
      end tell
   end tell
end tell
Using these Apple events many users can store data to the server at the same time. The server receives the versions, puts them into an incoming pool and takes care of storing these items space efficiently when there's nothing else to do.

Implementation Issues

Once you have designed your Object Model, you must implement the necessary handlers for resolving the Apple event object references and for processing the Apple events. This section gives some hints for implementing a server application and covers some implementation details that are particular for an AEOM based server application. The latter requires careful attention to identifying and maintaining multiple client/server connections.

First of all we want recommend you use an application framework that provides support for the AEOM in order to reduce your own implementation efforts. Metrowerks' PowerPlant is an example of an application framework that has extensive AEOM support. In PowerPlant, the AEOM can be implemented by adding classes to the framework using LModelObject as a base class and overriding methods to handle specific Apple events. PowerPlant already supports many of the events of the Core Suite. The exact details of implementing an AEOM in PowerPlant have been thoroughly described in (4).

Factor your Application

It is a good idea to factor your server application into domain-specific and communication-specific parts. This enables you to replace the communication layer of the server with a different protocol or to add support for other protocols. Figure 6 shows how this has been done in the VOODOO server application.

Figure 6. Structure of the VOODOO Server application.

The VOODOO Engine, which contains the code to access the data in the VOODOO database, is based on the ANSI C++ Standard Library only. The AEOM handling code is built on top of PowerPlant and calls the VOODOO engine to access the data in the VOODOO database. The very small user interface part of the VOODOO Server application also is based on PowerPlant.

Identifying Different PPC Sessions

An essential task of a server application is to keep track of all the connections of clients in order to be able to perform initializations when a new connection is established and cleanups when a connection is closed. Note that connections are not always closed explicitly by the client. The client process may crash and a server must be able to deal with this situation properly in order to ensure data integrity.

A TCP/IP based server has full control over its connections since it awaits and accepts new connections at a dedicated port. The server can easily keep track of all the connections that have been established by clients. When the client side unexpectedly closes the connection, an error is usually pending on the connection's socket on the server side.

With Apple events the situation is different. The Apple Event Manager does not explicitly inform the server application when a new session with a client is established. There is also no particular notification available when a session to a client application has been closed. Instead, the application receives all Apple events as high level events during normal event processing within the main event loop. The usual way to process an Apple event is to pass it to the Apple Event Manger function AEProcessAppleEvent, which then activates the appropriate Apple event Handler function.

However, the communication with Apple events is based on the PPC Toolbox. By using a combination of Apple Event Manger and PPC Toolbox calls, the developer can gain control over the server's session handling again. The following code examples illustrate how this can be done. The key idea is to wrap all the necessary Toolbox calls in a class PPCSession that represents a client's active connection to the server. For simplicity we use PowerPlant container classes in the following example code.

Class PPCSession

class PPCSession {
public:
   PPCSession(const AppleEvent& inAppleEvent);
   virtual PPCSessRefNum GetID();
   static PPCSession* FindSession(PPCSessRefNum inSessID);
   static void VerifySessions();
   virtual Boolean IsActive();
   virtual ~PPCSession();
protected:
   virtual void Closed();
   PPCSessRefNum                     mSessionID;
   PPCReadPBRec                      mPBRec;
   static TArray<PPCSession*>  sActiveSessions;
};

The class PPCSession can be used as is or as a base class for more elaborate session classes. The VOODOO Server overrides this class to add information for which user has logged on in this session and which projects the user has opened.

PPCSession::PPCSession

PPCSession::PPCSession(const AppleEvent& inAppleEvent)
{
   OSErr      err;
   Size         bogusSize;
   DescType   bogusType;
   TargetID   addr;
      
   err = ::AEGetAttributePtr(&inAppleEvent,
                  keyAddressAttr, typeTargetID,
                  &bogusType, &addr, sizeof(addr), &bogusSize);
   ThrowIfOSErr_(err);
   mSessionID = addr.sessionID;
   mPBRec.ioResult = 0;
   sActiveSessions.AddItem(this);
}

The constructor takes an Apple event as its only parameter and examines the address attribute of this Apple event. The address attribute contains the PPC session reference number of the underlying PPC session and the address of the machine on the AppleTalk network from which the Apple event was sent. The session reference number is stored in the instance variable mSessionID. The session object then inserts itself into the list of all active PPCSession objects. The instance variable mPBRec which is used by the IsActive method is initialized, too (see below).

PPCSession::GetID

PPCSessRefNum
PPCSession::GetID()
{
   return mSessionID;
}

The method GetID is an accessor function that returns the session reference number of the PPC session.

PPCSession:: FindSession

PPCSession*
PPCSession::FindSession(PPCSessRefNum inSessID)
{
   PPCSession* sess;
   TArrayIterator<PPCSession*> iterator(sActiveSessions);
   while (iterator.Next(sess)) {
      if (sess->GetID() == inSessID) {
         return sess;
      }
   }
   return nil;
}

The class method FindSession searches the list of all PPCSession objects for an object with the given Session Reference Number. The search is done using a PowerPlant iterator object.

PPCSession::VerifySessions

void
PPCSession::VerifySessions()
{
   PPCSession* sess;
   TArrayIterator<PPCSession*> iterator(sActiveSessions);
   while (iterator.Next(sess)) {
      if (!sess->IsActive()) {
         sess->Closed();
         delete sess;
      }
   }
}

PPCSession:: Closed

void
PPCSession::Closed()
{
   // should be overwritten!
}

VerifySessions is a class method that should be called periodically by the server application to verify that the server's connections are still intact. An ideal location for calling this method would probably be the idle handler of your application. The function iterates through the list of all PPCSession objects and deletes those objects whose underlying PPC session has been closed by the client side. Before the object is deleted, the message Closed is sent to the object. Derived classes of PPCSession can override the Closed method to perform cleanup tasks, when the connection has been unexpectedly closed. The VOODOO Server takes care of aborting any of the user's unfinished storage tasks, closing any of the user's opened projects, and logging off the user.

PPCSession::IsActive

Boolean
PPCSession::IsActive()
{
   if (mPBRec.ioResult == 0) {
      // test if session is still active 
      mPBRec.ioCompletion = nil;
      mPBRec.sessRefNum   = mSessionID;
      mPBRec.bufferLength = 0;
      mPBRec.bufferPtr    = nil;
      OSErr err = ::PPCReadAsync(&mPBRec);
      return (err == noErr);
   }
   else {
      // assume that session is active
      // if asynchronous call has not yet finished
      return (mPBRec.ioResult == 1);
   }
}

The actual check whether a PPC session is still intact is done inside the method IsActive. This function tries to read a zero length block from the PPC session, so no data is actually fetched, but an error message will be returned from the call when the session is no longer intact. The actual call of PPCRead is done asynchronously. Therefore the call's parameter block can not be declared as a local variable. For simplicity we made mPBRec an instance variable of the class PPCSession. If the asynchronous PPCRead call has not yet finished, it is assumed that the session is still active.

PPCSession::~PPCSession

PPCSession::~PPCSession()
{
   sActiveSessions.Remove(this);
   if (mPBRec.ioResult == 1) {
      // finishing asynchronous calls
      PPCEndPBRec pb;
      pb.ioCompletion = nil;
      pb.sessRefNum   = mSessionID;
      ::PPCEndSync(&pb);
   }
}

The classes' destructor removes the PPCSession object from the list of active sessions. If an asynchronous call is still pending for the session, this call is finished using the PPCEnd toolbox call. This is necessary since the parameter block mPBRec is not longer valid after the execution of the object's destructor.

MyAppleEventHandler

pascal OSErr
MyAppleEventHandler(
   const AppleEvent*   inAppleEvent,
   AppleEvent*            outAEReply,
   SInt32                     inRefCon)
{
   Size               bogusSize;
   DescType         bogusType;
   TargetID         addr;
   short            eventSource;
   PPCSession*      sess;

   err = ::AEGetAttributePtr(&inAppleEvent, keyAddressAttr,
           typeTargetID,
           &bogusType, &addr, sizeof(addr), &bogusSize);
   if (err != noErr) return err;
   sess = PPCSession::FindSession(addr.sessionID);
   if (sess == nil) {
      // a new session has been established
      sess = new PPCSession(inAppleEvent);
   }
   // continue with normal Apple event processing
}

The Apple event handler of your server application is the right place to create the session objects. The function MyAppleEventHandler sketches the necessary operations. The handler first examines the Apple event's address attribute to get the session reference number. If there is no PPCSession object valid for the session reference number, a new PPC session has been established by a client.

User Interaction

A server application usually runs unattended by the user on a remote machine. An Apple event based server application can thus not make use of the user interaction calls of the Apple Event Manager. The only way for the server application to interact with the user is to return error messages. The error message should contain both a unique error number and an error message string. For a further discussion of user interaction in Apple event based server applications see (6).

Concurrency

An Apple event server application can receive events from different client applications at the same time. While the server is busy handling an Apple event from one client, Apple events of other clients are delayed. It is important for the server to be as responsive to clients as possible, otherwise the server application becomes the bottleneck of the client/server system.

With Apple events the server has the possibility to suspend the handling of an Apple event using the AESuspendTheCurrenEvent toolbox call and continue processing other events. Execution of the suspended Apple event can be resumed later using the AESuspendTheCurrentEvent. Each suspended Apple event can then be assigned an own thread of execution. See (2) for details how to thread the execution of Apple events.

Conclusion

The Apple Event Object Model is an ideal choice when designing the protocol for a client-server-based application. This article discussed some issues you should consider when designing a protocol of a client/server system based on the AEOM. It showed the advantages of using Apple events and in particular the Apple Event Object Model. Thanks to the object-oriented nature of the AEOM the data provided by the server can be designed using an object-oriented approach. However, using Apple events as the communication basis for a client/server system also leads to some problems, especially what concerns the accurate control of connections. The paper finally presented a solution to gain the necessary control by using services of the PPC Toolbox.

Bibliography and References

  1. E. Gamma, R. Helm, R. Johnson, and J. Vlissides. Design Patterns,. Addison-Wesley, ISBN 0-201-63361-2, 1995
  2. Grant Neufeld. "Threading Apple Events". MacTech Magazine 12:4 (April 1996), pp. 33-40.
  3. Christoph Reichenberger. "Keeping Things Straight, Orthogonally" MacTech Magazine 12:6 (June 1996), pp. 61-70.
  4. Jeremy Roschelle. "Powering Up Apple Events in PowerPlant". MacTech Magazine 11:6 (June 1995), pp. 33-46.
  5. John Schettino. "The Tao of Design". MacTech Magazine 13:4 (April 1997), pp. 30-39.
  6. Cal Simone. "According To Script: User Interaction in Apple Event-Driven Applications". Develop, Issue 29 (May 1997), pp. 74-80.
  7. Cal Simone. "The AppleScript Scorecard Guidelines". MacTech Magazine 14:2 (February 1998), pp. 16-18.
  8. Cal Simone. "According To Script: An External Editing Apple Event Protocol". Develop in MacTech Magazine 13:5 (April 1997), pp. 30-39.

Sascha Kratky studied computer science at the Johannes Kepler University in Linz, Austria. After graduation he joined UNI SOFTWARE PLUS where he is working on the VOODOO project. You can reach Sascha by sending email to kratky@unisoft.co.at.

Christoph Reichenberger studied computer science at the Johannes Kepler University Linz, Austria. After that he worked there as an assistant professor for seven years and finalized his work with a PhD thesis on software configuration management. Then he joined UNI SOFTWARE PLUS where he is now managing the VOODOO product line which is an offspring of his former research work. He can be reached via email at chrei@unisoft.co.at. The home page of UNI SOFTWARE PLUS can be visited at http://www.unisoft.co.at.

 
AAPL
$524.94
Apple Inc.
+5.93
MSFT
$40.01
Microsoft Corpora
-0.39
GOOG
$536.10
Google Inc.
-20.44

MacTech Search:
Community Search:

Software Updates via MacUpdate

VMware Fusion 6.0.3 - Run Windows apps a...
VMware Fusion allows you to create a Virtual Machine on your Mac and run Windows (including Windows 8.1) and Windows software on your Mac. Run your favorite Windows applications alongside Mac... Read more
Tweetbot 1.5.1 - Popular iOS twitter cli...
Tweetbot is a full-featured OS X Twitter client with a lot of personality. Whether it's the meticulously-crafted interface, sounds and animation, or features like multiple timelines and column views... Read more
Mac DVDRipper Pro 4.1.7 - Copy, backup,...
Mac DVDRipper Pro is the DVD backup solution that lets you protect your DVDs from scratches, save your batteries by reading your movies from your hard disk, manage your collection with just a few... Read more
PDFpenPro 6.2 - Advanced PDF toolkit for...
PDFpenPro allows users to edit PDF's easily. Add text, images and signatures. Fill out PDF forms. Merge or split PDF documents. Reorder and delete pages. Even correct text and edit graphics! Create... Read more
PDFpen 6.2 - Edit and annotate PDFs with...
PDFpen allows users to easily edit PDF's. Add text, images and signatures. Fill out PDF forms. Merge or split PDF documents. Reorder and delete pages. Even correct text and edit graphics! Features... Read more
Monolingual 1.5.9 - Remove unwanted OS X...
Monolingual is a program for removing unnecesary language resources from OS X, in order to reclaim several hundred megabytes of disk space. It requires a 64-bit capable Intel-based Mac and at least... Read more
Maya 2015 - Professional 3D modeling and...
Maya is an award-winning software and powerful, integrated 3D modeling, animation, visual effects, and rendering solution. Because Maya is based on an open architecture, all your work can be scripted... Read more
Starcraft II: Wings of Liberty 1.1.1.180...
Download the patch by launching the Starcraft II game and downloading it through the Battle.net connection within the app. Starcraft II: Wings of Liberty is a strategy game played in real-time. You... Read more
Sibelius 7.5.0 - Music notation solution...
Sibelius is the world's best-selling music notation software for Mac. It is as intuitive to use as a pen, yet so powerful that it does most things in less than the blink of an eye. The demo includes... Read more
Typinator 5.9 - 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

Latest Forum Discussions

See All

Have a Special Dead Trigger 2 Easter Bas...
Have a Special Dead Trigger 2 Easter Basket Full of Goodies, Courtesy of Madfinger Games Posted by Rob Rich on April 18th, 2014 [ permalink ] Dead Trigger 2 | Read more »
Almost All of Playdek’s Library is on Sa...
Almost All of Playdek’s Library is on Sale Right Now, and You Should Check it Out Posted by Rob Rich on April 18th, 2014 [ permalink ] Playdek has released quite a few great iOS ports of board and card games over the years, and now most of them... | Read more »
Zynga Launches Brand New Farmville Exper...
Zynga Launches Brand New Farmville Experience with Farmville 2: Country Escape Posted by Tre Lawrence on April 18th, 2014 [ permalink ] | Read more »
David. Review
David. Review By Cata Modorcea on April 18th, 2014 Our Rating: :: MINIMALISTIC IN A DIFFERENT WAYUniversal App - Designed for iPhone and iPad David is a minimalistic game wrapped inside of a soothing atmosphere in which the hero... | Read more »
Eyefi Unveils New Eyefi Cloud Service Th...
Eyefi Unveils New Eyefi Cloud Service That Allows Users to Share Media Across Personal Devices Posted by Tre Lawrence on April 18th, 2014 [ permalink ] | Read more »
Tales from the Dragon Mountain: The Lair...
Tales from the Dragon Mountain: The Lair Review By Jennifer Allen on April 18th, 2014 Our Rating: :: STEADY ADVENTURINGiPad Only App - Designed for the iPad Treading a safe path, Tales from the Dragon Mountain: The Lair is a... | Read more »
Yahoo Updates Flickr App with Advanced E...
Yahoo Updates Flickr App with Advanced Editing Features and More Posted by Tre Lawrence on April 18th, 2014 [ permalink ] | Read more »
My Incredible Body - A Kid's App to...
My Incredible Body - A Kid's App to Learn about the Human Body 1.1.00 Device: iOS Universal Category: Education Price: $2.99, Version: 1.1.00 (iTunes) Description: Wouldn’t it be cool to look inside yourself and see what was going on... | Read more »
Trials Frontier Review
Trials Frontier Review By Carter Dotson on April 18th, 2014 Our Rating: :: A ROUGH LANDINGUniversal App - Designed for iPhone and iPad Trials Frontier finally brings the famed stunt racing franchise to mobile, but how much does its... | Read more »
Evernote Business Notebook by Moleskin I...
Evernote Business Notebook by Moleskin Introduced – Support Available in Evernote for iOS Posted by Tre Lawrence on April 18th, 2014 [ permalink ] | Read more »

Price Scanner via MacPrices.net

Deal Alert! 13-inch MacBook Pro on sale for $...
Best Buy has the 13″ 2.5GHz MacBook Pro on sale for $999.99 on their online store. Choose free shipping or free instant local store pickup (if available). Their price is $200 off MSRP. Price is valid... Read more
Free HopTo 2.2 Helps Enhance Your Productivit...
The HopTo app helps you do more on your iPad by providing more and easier adaccess to files and documents. Version 2.2 adds Egnyte and HopTo’s Mac OSX File Connector. If you already have the hopTo... Read more
National Distracted Driving Awareness Month:...
As the country recognizes National Distracted Driving Awareness Month, Sprint is reminding wireless consumers to focus on driving while behind the wheel, to not text or email while driving, and to... Read more
13-inch 2.4GHz Retina MacBook Pro available f...
Abt has the 13″ 2.4GHz 128GB Retina MacBook Pro available for $1229 including free shipping. Their price is $70 off MSRP. Read more
iMacs on sale for up to $160 off MSRP this we...
Best Buy has iMacs on sale for up to $160 off MSRP for a limited time. Choose free home shipping or free instant local store pickup (if available). Prices are valid for online orders only, in-store... Read more
iPad Airs on sale this weekend for up to $100...
Best Buy has WiFi iPad Airs on sale for $50 off MSRP and WiFi + Cellular iPad Airs on sale for $100 off MSRP on their online store for a limited time, with prices now starting at $449. Choose free... Read more
Apple restocks refurbished Mac minis starting...
The Apple Store has restocked Apple Certified Refurbished Mac minis for up to $150 off the cost of new models. Apple’s one-year warranty is included with each mini, and shipping is free: - 2.5GHz Mac... Read more
Hyundai Brings Apple CarPlay To The 2015 Sona...
Hyundai Motor America has announced it will bring Apple CarPlay functionality to the 2015 Sonata. CarPlay is pitched as a smarter, safer and easier way to use iPhone in the car and gives iPhone users... Read more
Updated iPads Coming Sooner Than We Had Thoug...
MacRumors, cites KGI securities analyst Ming Chi Kuo, well-respected as an Apple product prognisticator, saying that Apple will introduce an upgraded iPad Air and iPad mini in 2014/Q3, meaning the... Read more
Toshiba Unveils New High And Low End Laptop M...
Toshiba has announced new laptop models covering both the high-end and low-end of the notebook computer spectrum. Toshiba 4K Ultra HD Laptop Toshiba’s new Satellite P55t features one of the world’s... Read more

Jobs Board

*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
*Apple* Inc. Research Data Specialist - Appl...
…of Worldwide Market Research & Intelligence. The team is responsible for conducting Apple branded consumer market research. It is also responsible for analyzing data Read more
*Apple* Automotive Parts Department position...
Apple Automotive is one of the fastest growing dealer…and it shows. Consider making the switch to the Apple Automotive Group today! At Apple Automotive, we Read more
*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
*Apple* Retail - Manager - Holyoke - Apple I...
Job Summary Keeping an Apple Store thriving requires a diverse set of leadership skills, and as a Manager, you’re a master of them all. In the store’s fast-paced, Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.