TweetFollow Us on Twitter

Reminder DA
Volume Number:4
Issue Number:3
Column Tag:Forth Forum

Time Manager Reminder DA

By Jörg Langowski, MacTutor Editorial Board, Grenoble, France

Jörg Langowski is a bio-chemical engineer for a french concern and is a founding and current board member of MacTutor. He can be reached at EMBL, c/o I.L.L. 156x, Grenoble, Cedex, France F-38042. We encourage European authors to contact Jörg directly about submissions to MacTutor.

“Using the Time Manager”

One thing I always wanted to have on my Mac is some utility that reminds me of an appointment, no matter what I’m doing on the machine at any given time. On our VAX, for example, there is this great program called Reminder which sits in the background and will beep at you when your next appointment arrives.

In the new system (128K ROMs and up) there exists a set of routines called the Time Manager. I thought it would be a good idea to show you their usage in developing a Reminder utility similar to the one on the VAX. In the process, I’ll show you how to work with modeless dialogs from a DA, how to call memory manager dependent traps from a time manager task, and some more.

The Time Manager

The Time manager is used to execute a task at a predetermined time. Its routines are documented in IM Vol. 4. All time manager tasks are described by entries in the time mamager queue, where each element has the following format:

header TMtask 14 allot
0 CONSTANT qLink
4 CONSTANT qType
6 CONSTANT tmTask
10 CONSTANT tmCount

That means, the queue entry looks just like a regular queue element, with two 4-byte fields, tmTask and tmCount, relevant to our task. tmTask contains a pointer to the routine to be executed, and tmCount is used by the system to count down the elapsed time. When it has reached zero, the task at tmTask will be executed.\

Three routines are provided by the time manager: InsTime, called with a pointer to the queue element in A0, will insert this queue element into the time manager queue. PrimeTime, with the queue element pointer in A0 and a 32-bit count in D0, will schedule the routine specified in that queue element to be executed after count milliseconds have elapsed. RmvTime, with a pointer to the queue element in A0, will remove the queue element. The Mach2 interface to these routines is given at the beginning of listing 1.

Fig. 1 Our Reminder DA lets Mac Widows post alerts for late night programmers!

Programming the Reminder utility

The strategy to follow seems very simple: we create a desk accessory that allows us to enter a message text and a delay time, that desk accessory will then setup a queue element with a pointer to a routine that displays an alert box containing that string.

Thinking about it, programming such a utility is not quite so simple. First of all, the routine passed to the time manager for execution cannot be part of the desk accessory. We’d like to enter appointments that are due in several hours or days (32 bits of milliseconds, unsigned, give a maximum possible delay of 49.7 days), and we’ll most probably have left the application where the desk accessory was started by then. Under MultiFinder this doesn’t matter, but under Finder, the desk accessory would have been closed, leaving the task pointer point to anything but the desired code.

My first thought was to use a ‘stick-around’ desk accessory that would automatically restart itself after an involuntary close, like I described earlier. But it is actually much easier to put a copy of the routine to be executed into a small block of system heap, leaving it independent of the DA. Then, one has to take caution that the routine, once executed, will remove its own queue entry and dispose of its own memory.

The second problem is that a time manager task may be executed at any time, interrupting whatever else is being done at that moment. For the same reason as in the case of VBL tasks, we may not call any routines from the time manager task that can move things around in the heap. If we did, there would be a chance that the interrupt occurs right in the middle of a memory manager operation, or while a handle hangs around dereferenced somewhere.

The time manager task must therefore be rather simple. I use the same trick as I described for the ‘stick-around’ DA, patching SystemTask from the scheduled routine. The next time SystemTask is called (which should happen rather soon in any benign application) the patch routine will be executed, which then can do the more involved stuff such as drawing an alert box.

Now look at the first part of the example: the routine that is executed by the time manager is contained between the markers mytask and mytask.end. The first bytes of this block contain the queue element. The name string ‘Reminder’ follows for debugging purposes. Some local variable space is reserved, where the original SystemTask trap address, the alert ID and the alert message can be kept. The SystemTask patch routine alertMe follows. It will display a note alert with the message in parameter ^0, unlock the alert, remove the time manager queue element and dispose of the memory allocated for itself.

Fig.2 After time has elapsed, an alert pops up!

alertMe is patched into SystemTask by the following routine, wakeMe, which is the one first executed by the time manager. A pointer to wakeMe will be contained in the tmTask field of the queue element at the beginning of the block. Since we do not know yet where this routine will be located, we’ll have to install the pointer after moving the code into the system heap.

As you see, the code between mytask and mytask.end is completely self-contained (as long as the ALRT resource can be found). We may therefore move any number of these little code blocks into the system heap and install their queue elements using the time manager; each will be executed at its scheduled time and display its little message. Appointment ‘objects’, so to say.

The desk accessory

The DA is used to install the tasks. It is a very simple DA which just draws up a modeless dialog box with two editable text items. The dialog window will have the driver reference number in its windowKind field, so that the system will handle mouse down events in the close box and drag region. Only when the event is passed through to the DA, windowKind will be temporarily set to 2 (dialog window), so that IsDialogEvent and DialogSelect work correctly.

When the OK button in the dialog box has been clicked, the dialog handler will be invoked. This routine converts the string in item 4 to a number, the delay in seconds, and gets the message to be displayed after this delay (item 3). These parameters are passed to install.wakeup, together with the alert ID. install.wakeup gets the wakeup routine described above from the resource file and installs a copy of it in the system heap. It saves a pointer to the wakeup routine in the tmTask field of the queue element, stores the alert ID and the message string at their appropriate positions and then schedules the routine for execution by calling InsTime and PrimeTime.

Things missing

The desk accessory described here is already quite useful ‘as is’. However, one could include some improvements that I leave as an exercise for you (or me, for that matter):

- Input of the appointment time in standard date format.

- Keeping a list of appointments that can be displayed and edited.

- Saving this list to a file every time it is changed; this file is then checked on system startup and the pending appointments rescheduled automatically.

I wish you good luck with those experiments; now, some mail that I recently received.

Feedback Dept.

“Dear Jörg,

I read your recent column in MacTutor with great interest and would like to obtain the addresses for Serge Rostan and also for Winsoft. [Serge Rostan, “TechnoPro”, rue Faraday, F-78180 Montigny le Bretonneux, France, phone (33) 1 30 45 26 62, and Winsoft, 34, boulevard de l’Esplanade, F-38000 Grenoble, France, phone (33) 76 87 56 01 - JL].

We are in the process of completing a book on fonts for the Macintosh for European and many other non-Roman languages. It will also show specimens of over 2000 bit-mapped and several hundred PostScript fonts.

If you can suggest any font vendors that do not advertise in US Macintosh magazines, it would be very helpful [not off the top of my head, but I’ll look around - JL].

As you may know, Apple refuses to sell European keyboards in the US, even to certified developers. Users here must cultivate acquaintances overseas and buy them indirectly. Do you know whether Apple tries to prevent the export of such keyboards from Europe? We would like to be able to list a commercial source for such keyboards in our book, but do not want to cause difficulties for anyone there. If they are readily available for export, we would appreciate the name of a recommended source.

[You address a problem that I’ve encountered myself. There seems no way for Macintosh developers in France to get other than French keyboards through the developer program. However, there is at least one Apple dealer in Grenoble who sells the US keyboard on request; we have several international research institutions here, so there’s a market. I’ll send you addresses of some Apple dealers in Germany and France that you might be able to order from.

I don’t think there are any export restrictions imposed by Apple on non-US keyboards into the US (unless you re-sell them to Colonel Kh...). The problem most probably is the bureaucracy that inevitably builds up in a large corporation, even one like Apple that for a while tried to maintain some ‘non-conformistic hacker’ kind of image. Which it is trying to forget at a rapid rate, I presume. Someone, it seems, must have set a guideline that in country X only systems localized for X will be sold, with few exceptions. The only way I get the most recent US system updates is through US sources, too. Funniest of all: The MacII system that I finally got a week ago (yes, I love it), has English documentation, US system disks (but 4.1, not 4.2, which is not officially released at the time I write this), but no way can I get a US keyboard. Probably the people at Apple France just wanted to be nice and ship me as many US parts as possible, but then they had only French keyboards. What a nuisance to have all the numbers on the top row...]

Lastly, Apple also tries to limit the availability of any Script Manager code or fonts it has developed to the country for which it was developed! This seems strange given that the Macintosh is touted as a Multinational machine. Apple has made Kanji and Arabic available through APDA, but feels that they are sufficient for the testing purposes intended. They have also developed a Chinese, a Hebrew and a Greek. The Chinese is distributed from Hong Kong and the Hebrew and Greek are distributed from Paris. I have written to the Paris office to no avail after a conversation with Mark Davis at Apple, the creator of the Script Manager. Do you know of a way for someone in the US to get these fonts from Paris? Actually, I am more interested in finding out the arrangement of characters in the coding table than I am in the font, but the exact status of ‘dead’ keys might be hard to discern accurately without actually having the font in hand.

Best regards,

Tim Ryan, SourceNet, Santa Barbara, CA “

[You address a very timely issue, that’s why I have your letter printed immediately without having the answers on hand yet. I’ll forward your mail with my comments to Apple France. I’m actually quite optimistic that you can get the Script Manager versions that you want. JL]

One comment to the letter from Peter Adamson, MT V4#1, p.11: The Pascal equivalent to the Mach2 PAUSE is actually WaitNextEvent; much like PAUSE under Mach2, WaitNextEvent will transfer control to the next MultiFinder task under certain circumstances. If you have a very long event loop, you may try to intersperse WaitNextEvents with event masks of zero, so that they’ll always return a null event. That should transfer control to the next task under MultiFinder. Only the crucial WaitNextEvent - the one with the BIG case statement behind it - would be called with a non-zero event mask. This is all untested, so don’t blame me if it doesn’t work.

See you next month.

Listing 1: Appointment reminder using the time manager
\ ***** Time manager example - a ‘reminder’ utility
\ J. Langowski December 87 
\
\ Strategy: write a driver that sets up a dialog which allows 
\ to enter a time & message to display after that time. After 
\ the appointment has been entered, the driver sets up a 
\ time manager call for that appointment.
\ The time manager routine installs a SystemTask trap 
\ patch which at the next occasion will draw an alert box 
\ containing the message to be displayed. 
\
\ Note that we have to use the patch rather than calling 
\ the alert routine directly from our time manager task,
\ since we can’t be sure we’re not in the middle of a 
\ memory manager operation when it is called.
\

only forth also assembler also mac

CODE InsTime ( tmTaskPtr | -- )
 MOVE.L (A6)+,A0
 _InsTime
 RTS
END-CODE MACH

CODE PrimeTime ( tmTaskPtr count | -- )
 MOVE.L (A6)+,D0
 MOVE.L (A6)+,A0
 _PrimeTime
 RTS
END-CODE MACH

CODE RmvTime ( tmTaskPtr | -- )
 MOVE.L (A6)+,A0
 _RmvTime
 RTS
END-CODE MACH

4ascii MENU constant “menu
4ascii PROC constant “proc

\ *** compiler support words for external definitions *** 
: :xdef 
 create -4 allot
 $4EFA w, ( JMP )
 0 w,  ( entry point to be filled later )
 0 ,   ( length of routine to be filled later )
 here 6 - 76543
;

: ;xdef { branch marker entry | -- }
 marker 76543 <> abort” xdef mismatch”
 entry branch - branch w!
 here branch - 2+ branch 2+ !
; 
 
: xlen 4 + @ ; ( get length word of external definition )

( *** driver header block *** )

 0 CONSTANT drvrFlags
 2 CONSTANT drvrdelay 
 4 CONSTANT drvrEMask
 6 CONSTANT drvrMenu
 8 CONSTANT drvrOpen
10 CONSTANT drvrPrime
12 CONSTANT drvrCtl
14 CONSTANT drvrStatus
16 CONSTANT drvrClose
18 CONSTANT drvrname
50 CONSTANT DAlength

\ *** compiler support words for DA and driver definitions 
: :DA 
 create -4 allot
 here 87654 ( start of DA block, and marker )
 50 allot   ( length of block )
;

: ;DA { DAstart marker Ropen Rprime Rctl Rstatus Rclose
 Rflags Rdelay Remask Rmenu Rname | -- }
 marker 87654 <> abort” DA definition mismatch”
 Ropen  DAStart - DAStart drvrOpen + w!
 Rprime DAStart - DAStart drvrPrime + w!
 Rctl   DAStart - DAStart drvrCtl + w!
 Rstatus  DAStart - DAStart drvrStatus + w!
 Rclose DAStart - DAStart drvrClose + w!
 Rflags DAStart drvrFlags + w!
 Rdelay DAStart drvrDelay + w!
 Remask DAStart drvrEmask + w!
 RMenu  DAStart drvrMenu + w!
 Rname count dup DAStart drvrName + c!
 DAStart drvrName + 1+ swap 
 dup 31 > if drop 31 then cmove 
 here DAstart -    DAStart DAlength + !
; 
 
: DAlen DAlength + @ ;
\ get length word of external definition

\ **** DA glue macros

CODE DA.prelude
 LINK A6,#-512 \ 512 bytes of local Forth stack
 MOVEM.L A0-A1,-(A7) \ save registers
 MOVE.L  A6,A3 \ setup local loop return stack
 SUBA.L   #256,A3  \ in the low 256 local stack bytes
 MOVE.L  A0,-(A6)  \ parameter block
 MOVE.L  A1,-(A6)\ device control entry
 RTS  \ just to indicate the MACHro stops here 
END-CODE MACH

CODE DA.epilogue
 MOVE.L  (A6)+,D0\ return code
 MOVEM.L (A7)+,A0-A1 \ restore registers
 UNLK A6
 RTS
END-CODE MACH

CODE DA.Jiodone
 MOVE.L  (A6)+,D0\ return code
 MOVEM.L (A7)+,A0-A1 \ restore registers
 UNLK A6
 move.l JIODone,A0
 movem.l d4-d7/a4-a6,-(a7)
 jsr    (a0)
 movem.l(a7)+,d4-d7/a4-a6
 RTS
END-CODE MACH

.TRAP _newptr,sys$A51E

%0000000101001010 CONSTANT DAEmask

$1B4 CONSTANT SystemTask

\ ____________________________________________
\ time manager and systemTask patch routine
\ this routine must reside in a block allocated 
\ in the system heap through a pointer. 
\ ____________________________________________

header myTask 14 allot
6 CONSTANT taskPtr
HEADER myName
 DC.B   9,0,’Reminder’
header myTrap 4 allot
header myAlert 4 allot
header myString 256 allot

: alertMe 
 MOVEM.LA0-A4/A6/D0-D7,-(A7)
 LINK A6,#-128 \ 128 bytes of local Forth stack
 (call) frontwindow windowkind + @
 2 <> IF
 [‘] myTrap @ SystemTask (call) SetTrapAddress
 [‘] myString 0 0 0 (call) paramText
 [‘] myAlert @ 0 (call) noteAlert drop
 [‘] myAlert @ (call) freeAlert
 [‘] myTask RmvTime
 [‘] myTask (call) DisposPtr drop
 THEN
 UNLK A6
 MOVEM.L(A7)+,A0-A4/A6/D0-D7
;

: wakeMe
 SystemTask (call) GetTrapAddr [‘] myTrap !
 [‘] alertMe SystemTask (call) SetTrapAddr
;

header mytask.end
‘ wakeme ‘ mytask - CONSTANT *wakeme \ task offset
‘ myAlert ‘ mytask - CONSTANT *myAlert \ alertID 
‘ myString ‘ mytask - CONSTANT *myString \ alert string

\ ___________________________________________
\ desk accessory code starts here.
\ ___________________________________________

:DA reminder 
 .ALIGN

( *** main desk accessory routines *** )
header myRes0 4 allot\ local res ID=0 offset 
header dlgText 256 allot

\ redefinition of cmove to make it 
\ available locally

CODE cmove
 move.l (a6)+,d0
 move.l (a6)+,a1
 move.l (a6)+,a0
 tst.l  d0
 ble.s  @2
@1 move.b (a0)+,(a1)+
 subq.l #1,d0
 bne.s  @1
@2 rts
END-CODE

\ ___________________
\ wakeup routine installation
\ ___________________

: install.wakeup 
 { delay alrtID msg | procHdl hSize taskBlock -- }
 
 “proc [‘] myRes0 @ (call) GetResource -> procHdl
 procHdl (call) getHandleSize -> hSize
 hSize MOVE.L (A6)+,D0
 _newPtr,sys
 MOVE.L A0,-(A6) -> taskBlock
 procHdl @ taskBlock hSize cmove
 procHdl (call) releaseResource
   \ we have made a local copy of the wakeup routine
 taskBlock dup *wakeMe + swap taskPtr + !
 msg taskBlock *myString + 256 cmove
 alrtID taskBlock *myAlert + !
 alrtID (call) CouldAlert
 taskBlock InsTime
 taskBlock delay PrimeTime
 \ now the wakeup routine will wake up after
 \ the scheduled delay.
;

: getDrvrID { dCtlEntry | -- num }
 dCtlEntry dCtlRefNum + w@ l_ext
 1+ negate
;

: ownResID ( resID drvrID )
 5 shl + -16384 +
;
: Open { parblk dce | DAWind Res0 -- returncode }
 5 (call) sysbeep 
 \ to get attention if automatically opened
 0 dce getDrvrID ownResID -> Res0
 dce dCtlWindow + @ -> DAWind
 DAWind 0= IF ( not open already )
 Res0 [‘] myRes0 !
 Res0 0 -1 (call) getNewDialog -> DAWind
 DAWind  dce dCtlWindow + !  
 \ store dialog pointer
 DAWind  dce dCtlRefNum + w@  
 swap windowKind + w!
 ELSE
 DAWind (call) selectWindow
 THEN
 0
;
: Close { parblk dce | -- returncode }
 dce dCtlWindow + 
 dup @ (call) DisposDialog  
 0 swap ! ( so that Open will work again )
 0
;
: dialog-handler 
 { dlgPtr itemHit | 
 itemType hItem rBox seconds -- }

\ we get here if the OK button in the dialog
\ has been hit, therefore itemHit is always =1 
\ - in our case. But it is nice to have itemHit
\ available, to be more general. 
\ item #3 contains the appointment message
\ item #4 contains the delay in seconds
\ (decimal number string)

 dlgPtr 4 ^ itemType ^ hItem ^ rBox (call) GetDItem
 hItem [‘] dlgText (call) GetIText
 [‘] dlgText (call) StringToNum -> seconds
 seconds 0> IF
 dlgPtr 3 ^ itemType ^ hItem ^ rBox 
 (call) GetDItem
 hItem [‘] dlgText (call) GetIText
 seconds 1000 w* 
 [‘] myres0 @ [‘] dlgText install.wakeup
 ELSE 10 (call) sysbeep
 THEN
;

: Ctl { parblk dce | 
 DAWind event-rec dlgPtr itemHit -- returncode }
 dce dCtlWindow + @ -> DAWind

 parblk csCode + w@ l_ext 
 CASE
 accEvent OF
 2 DAWind windowKind + w! 
 \ set to dialog window 
 parblk csParam + @ -> event-rec
 event-rec (call) IsDialogEvent
 IF  event-rec ^ dlgPtr ^ itemHit
 (call) Dialogselect
 IF dlgPtr itemHit dialog-handler THEN
 THEN
 DAWind  dce dCtlRefNum + w@  
 swap windowKind + w! 
 \ reset windowkind
 ENDOF

 ENDCASE
 0
;
: DrOpen DA.Prelude Open DA.Epilogue ;
: DrClose DA.Prelude Close DA.Epilogue ;
: DrCtl DA.Prelude Ctl DA.JioDone ;
: DrStatus ;
: DrPrime ;

‘ DrOpen ‘ DrPrime ‘ DrCtl ‘ DrStatus ‘ DrClose
$7400 \ need lock, need time, need goodbye, ctl calls
60 DAEmask 0 \ delay mask menu
“ Reminder” \ name
;DA


( write resource to file ) 
: $create-res ( str-addr - errcode )
 call CreateResFile
 call ResError L_ext
;
: $open-res { addr | refNum - refNum or errcode }
 addr call OpenResFile -> refNum
 call ResError L_ext
 ?dup IF ELSE refNum THEN
; 
: close-res ( refNum - errcode )
 call CloseResFile
 call ResError L_ext
;
: make-res { addr len rtype ID name | -- }
 addr len call PtrToHand 
 abort” Could not create resource handle”
 rtype ID name call AddResource
;
: write-out { filename | refnum -- } 
 filename $create-res 
 abort” That resource file already exists”
 filename $open-res
 dup 0< abort” Open resource file failed”
 -> refnum
 refnum call UseResFile
 [‘] reminder dup DALen
 “drvr 12 “ Reminder” make-res
 [‘] myTask [‘] mytask.end over - 
 “proc -16000 “ wakeUp” make-res
 “proc -16000 call GetResource
 dup 80 call SetResAttrs  
 ( 64: sysheap + 16: locked )
 call ChangedResource
 refnum close-res 
 abort” Could not close resource file”
;
: make-DA
 “ Reminder.rsrc” $delete drop
 “ Reminder.rsrc” write-out
;
 
AAPL
$116.47
Apple Inc.
+0.16
MSFT
$47.98
Microsoft Corpora
-0.72
GOOG
$537.50
Google Inc.
+2.67

MacTech Search:
Community Search:

Software Updates via MacUpdate

Cobook 3.0.7 - Intelligent address book....
Cobook Contacts is an intuitive, engaging address book. Solve the problem of contact management with Cobook Contacts and its simple interface and powerful syncing and integration possibilities.... Read more
StatsBar 1.9 - Monitor system processes...
StatsBar gives you a comprehensive and detailed analysis of the following areas of your Mac: CPU usage Memory usage Disk usage Network and bandwidth usage Battery power and health (MacBooks only)... Read more
Cyberduck 4.6 - FTP and SFTP browser. (F...
Cyberduck is a robust FTP/FTP-TLS/SFTP browser for the Mac whose lack of visual clutter and cleverly intuitive features make it easy to use. Support for external editors and system technologies such... 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
Evernote 6.0.1 - Create searchable notes...
Evernote allows you to easily capture information in any environment using whatever device or platform you find most convenient, and makes this information accessible and searchable at anytime, from... Read more
calibre 2.11 - Complete e-library manage...
Calibre is a complete e-book library manager. Organize your collection, convert your books to multiple formats, and sync with all of your devices. Let Calibre be your multi-tasking digital... Read more
Herald 5.0.1 - Notification plugin for M...
Note: Versions 2.1.3 (for OS X 10.7), 3.0.6 (for OS X 10.8), and 4.0.8 (for OS X 10.9) are no longer supported by the developer. Herald is a notification plugin for Mail.app, Apple's Mac OS X email... Read more
Firetask 3.7 - Innovative task managemen...
Firetask uniquely combines the advantages of classical priority-and-due-date-based task management with GTD. Stay focused and on top of your commitments - Firetask's "Today" view shows all relevant... Read more
TechTool Pro 7.0.6 - Hard drive and syst...
TechTool Pro is now 7, and this is the most advanced version of the acclaimed Macintosh troubleshooting utility created in its 20-year history. Micromat has redeveloped TechTool Pro 7 to be fully 64... Read more
PhotoDesk 3.0.1 - Instagram client for p...
PhotoDesk lets you view, like, comment, and download Instagram pictures/videos! (NO Uploads! / Image Posting! Instagram forbids that! AND you *need* an *existing* Instagram account). But you can do... Read more

Latest Forum Discussions

See All

Ubisoft Gives Everyone Two New Ways to E...
Ubisoft Gives Everyone Two New Ways to Earn In-Game Stuff for Far Cry 4 Posted by Jessica Fisher on November 21st, 2014 [ permalink ] | Read more »
Golfinity – Tips, Tricks, Strategies, an...
Dig this: Would you like to know what we thought of being an infinite golfer? Check out our Golfinity review! Golfinity offers unlimited ways to test your skills at golf. Here are a few ways to make sure your score doesn’t get too high and your... | Read more »
Dark Hearts, The Sequel to Haunting Meli...
Dark Hearts, The Sequel to Haunting Melissa, is Available Now Posted by Jessica Fisher on November 21st, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Meowza! Toyze Brings Talking Tom to Life...
Meowza! | Read more »
Square Enix Announces New Tactical RPG f...
Square Enix Announces New Tactical RPG for Mobile, Heavenstrike Rivals. Posted by Jessica Fisher on November 21st, 2014 [ permalink ] With their epic stories and gorgeous graphics, | Read more »
Quest for Revenge (Games)
Quest for Revenge 1.0.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0.0 (iTunes) Description: The great Kingdom of the west has fallen. The gods ignore the prayers of the desperate. A dark warlord has extinguished... | Read more »
Threadz is a New Writing Adventure for Y...
Threadz is a New Writing Adventure for You and Your Friends Posted by Jessica Fisher on November 21st, 2014 [ permalink ] In the tradition of round-robin storytelling, | Read more »
SteelSeries Stratus XL Hardware Review
Made by: SteelSeries Price: $59.99 Hardware/iOS Integration Rating: 4 out of 5 stars Usability Rating: 4.5 out of 5 stars Reuse Value Rating: 4.25 out of 5 stars Build Quality Rating: 4.5 out of 5 stars Overall Rating: 4.31 out of 5 stars | Read more »
ACDSee (Photography)
ACDSee 1.0.0 Device: iOS iPhone Category: Photography Price: $1.99, Version: 1.0.0 (iTunes) Description: Capture, perfect, and share your photos with ACDSee. The ACDSee iPhone app combines an innovative camera, a powerful photo... | Read more »
ProTube for YouTube (Entertainment)
ProTube for YouTube 2.0.2 Device: iOS Universal Category: Entertainment Price: $1.99, Version: 2.0.2 (iTunes) Description: ProTube is the ultimate, fully featured YouTube app. With it's highly polished design, ProTube offers ad-free... | Read more »

Price Scanner via MacPrices.net

Save up to $400 with Apple refurbished 2014 1...
The Apple Store has restocked Apple Certified Refurbished 2014 15″ Retina MacBook Pros for up to $400 off the cost of new models. An Apple one-year warranty is included with each model, and shipping... Read more
New 13-inch 1.4GHz MacBook Air on sale for $8...
 Adorama has the 2014 13″ 1.4GHz/128GB MacBook Air on sale for $899.99 including free shipping plus NY & NJ tax only. Their price is $100 off MSRP. B&H Photo has the 13″ 1.4GHz/128GB MacBook... Read more
Apple Expected to Reverse Nine-Month Tablet S...
Apple and Samsung combined accounted for 62 percent of the nearly 36 million branded tablets shipped in 3Q 2014, according to early vendor shipment share estimates from market intelligence firm ABI... Read more
Stratos: 30 Percent of US Smartphone Owners t...
Stratos, Inc., creator of the Bluetooth Connected Card Platform, has announced results from its 2014 Holiday Mobile Payments Survey. The consumer survey found that nearly one out of three (30 percent... Read more
2014 1.4GHz Mac mini on sale for $449, save $...
 B&H Photo has lowered their price on the new 1.4GHz Mac mini to $449.99 including free shipping plus NY tax only. Their price is $50 off MSRP, and it’s the lowest price available for this new... Read more
Check Apple prices on any device with the iTr...
MacPrices is proud to offer readers a free iOS app (iPhones, iPads, & iPod touch) and Android app (Google Play and Amazon App Store) called iTracx, which allows you to glance at today’s lowest... Read more
64GB iPod touch on sale for $249, save $50
Best Buy has the 64GB iPod touch on sale for $249 on their online store for a limited time. Their price is $50 off MSRP. Choose free shipping or free local store pickup (if available). Sale price for... Read more
15″ 2.2GHz Retina MacBook Pro on sale for $17...
 B&H Photo has the 2014 15″ 2.2GHz Retina MacBook Pro on sale for $1799.99 for a limited time. Shipping is free, and B&H charges NY sales tax only. B&H will also include free copies of... Read more
New Logitech AnyAngle Case/Stand Brings Flexi...
Logitec has announced the newest addition to its suite of tablet products — the Logitech AnyAngle. A protective case with an any-angle stand for iPad Air 2 and all iPad mini models, AnyAngle is the... Read more
Notebook PC Shipments Rise Year-Over-Year as...
According to preliminary results from the upcoming DisplaySearch Quarterly Mobile PC Shipment and Forecast Report, the global notebook PC market grew 10 percent year-over-year in Q3’14 to 49.4... 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* Solutions Consultant (ASC)- Retail S...
**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
Project Manager, *Apple* Financial Services...
**Job Summary** Apple Financial Services (AFS) offers consumers, businesses and educational institutions ways to finance Apple purchases. We work with national and Read more
*Apple* Store Leader Program - College Gradu...
Job Description: Job Summary As an Apple Store Leader Program agent, you can continue your education as you major in the art of leadership at the Apple Store. You'll Read more
*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.