The DigitaOS: An Extensible Imaging Platform
by Carlos E. Vidales and Eugene M. Farrelly


Listing One
#include <FPApplicationManager.h>
#include <FPEventManager.h>
TVoidPtr entry(void)
{
  TAMAppID           appId ;
  TEMEventRecord   * theEvent ;
  TBoolean           doExit ;
  AppInit() ;
  RegisterForEvents() ;
  while( !doExit )
  {
    EMGetEvent( appId, &theEvent ) ;
    doExit = HandleEvent( &theEvent ) ;
  }
  AppExit() ;
  return(NULL);
}


Listing Two
# Sample configuration file for extended time-lapse application
# Turn logging on to catch any errors during command execution
Log on
# Label statement for flow control with goto statements
Label repeat
# Wake at 1:30:00 pm
wake 13 30 00
# Zoom to 2x magnification
zoom 200
# Capture 1 image
capture 1
# Zoom out
Zoom out
# Capture 1 image
capture 1
# Repeat the sequence
goto repeat

Listing Three
/* structure of a node in the doubly linked list */
struct cmd_list
{
    TErrCo          (* cmdFunc) ();
    TShort             argc;
    TChar           ** argv;
    TShort             cmdMinNumOfArgs;
    TShort             fileLineNum;
    TBoolean           isResolved;
    TShort             cmdExecutionCounter;
    struct cmd_list  * nextCmd;
    struct cmd_list  * prevCmd;
} ;


Listing Four
/* entry point for Digita apps */
TInt entry(TInt argc, TChar **argv)
{
  TErrCo          err = kNoErr,
                  appErr = kNoErr;
  TAMAppID        appID = 0;
  sigset_t        pendingSet;
  TBoolean        alarmSignal;
  TEMEventRecord *theEvent;
  TChar           text[kMaxTextLength];
  TBoolean        doExit;

  // Start the necessary subsystems according to app content.
  err = ProcessInit();
  // Start the graphics subsystem and display a global banner....
  if (kNoErr == (err = SDKDInit(TRUE)))
  {
      LMEnableLCDController() ;
      SDKDDrawTextandScrollUp("  Digita Sample Application  ");
  }
  else
  {
      return(NULL);
  }
  // Process functions before enabling button events.  
  err = ProcessBeforeEventLoop();

  // Get the application ID and ensure it's valid
  if (0 == (appID = RegisterWithEventManager()))
       err = !kNoErr;  // Set to not no-error
  gAppID = appID ;
  SDKDDrawTextandScrollUp("Press Menu button for options");
  // Process while there are no system event errors   
  doExit = FALSE ;
  while ( (err == kNoErr) && !doExit )
  {
    // Block & wait for next event. Event subsystem allocated mem for event.
    err = EMGetEvent( appID, &theEvent);
    if (err != kNoErr)
    {
      //Handle a signal that is posted.
      if (0 == sigpending(&pendingSet))
      {
        alarmSignal = sigismember(&pendingSet, SIGALRM);
        err = kNoErr;
      }
    }
    else
    {
      // Got an event, now Handle it.  
      appErr = HandleEvent(theEvent, &doExit);
      // Release the event, specifically the mem allocated
      EMReleaseEventRecord(theEvent);
      // Now check the application error.
      if ((err == kNoErr) && (appErr != kNoErr))
      {
        err = appErr;
      }
    }
  }
  // Exit the application.
  SDKDScrollUp();
  sprintf( text, "Exiting sample, rc = %ld", FPERROR(err) );
  SDKDDrawTextandScrollUp(text);
  DelayTime( 30 ) ;   // let me see the message ...
  err = SDKDTerminate();  //Terminate the graphic manager
  err = ProcessTerm();   // ProcessTerm() will turn off the camera.
  return(NULL);
} // entry


Listing Five
TErrCo ProcessButtonEvent(const TBTNDigitaButtonId buttonID, 
                             const TBTNDigitaButtonPosition buttonState)
{
  TErrCo err = kNoErr;
  switch (buttonID)
  {
    case kDigitaSoftKey2:
      CenterSoftkeyButton(buttonState);
      break;
    default:
      break;
  }
  return(err);
} // ProcessButtonEvent


Listing Six
TVoid CenterSoftkeyButton(TBTNDigitaButtonPosition buttonState)
{
  TErrCo err = kNoErr;
  TChar  msg[kMaxTextLength];
  if (!sCommandProcessorStarted)
  {
    if (buttonState == kButtonUp)
    {
      if (sCommandInitSuccess)
      {
        // set a flag disable button events (except power down)
        sCommandProcessorStarted = TRUE;
        // Start with the first command
        CommandGoToCmdStart();
        if (kNoErr != (err = CommandDispatch(gCmdCur,FALSE)))
        {
          sprintf(msg,sDispatchEventError, FPERROR (err));
          SDKDDrawTextandScrollUp(msg);
        }
      }
      else
      {
        sprintf(msg,"Commands contained errors.");
        SDKDDrawTextandScrollUp(msg);
      }
    }
  }
 return;
} // CenterSoftkeyButton

Listing Seven
TErrCo CommandDispatch(TCmdData * pCmd, TBoolean validate)
{
  TErrCo   err = kNoErr;

  // if arg is null, use current command
  if (pCmd == NULL)
  {
      pCmd = gCmdCur;
  }
  // Record the time when the command is dispatched
  CommandGetTime(&sCurSystemTime,&sCurTmTime);
  // Dispatch the command
  if (pCmd != NULL)
  {
      err = (*(pCmd->cmdFunc)) (pCmd,validate);
  }
  else
  {
      // Current command is not set
      err = kCurrentCmdNotSetErr;
  }
  if (sLoggingEnabled)
  {
    // Log the command
    CommandLogCmd(FPERROR (err));
  }
  return(err);
} // CommandDispatch

Listing Eight
// Convert the zoom value to an integer
zoomValue = atoi(pCmd->argv[zoomIndex]);
// Retrieve the current zoom position setting
if (kNoErr == (err = PARMGetCurrentSetting( kFTAGzpos, &nameTypeValue )))
{
  // Set the zoom position
  nameTypeValue.fTypeValue.fValue.fUint = zoomValue ;
  // write the structure back to make it take effect.
  err = PARMSetCurrentSetting( kFTAGzpos, &(nameTypeValue.fTypeValue) );
}

Listing Nine
TInt LocalCaptureSpoolingComplete(TVoidPtr data)
{
  TErrCo err = kNoErr;
  DispatchEvent(fData0_Group,fData1_Spooled,"Capture spooling complete");
  return(err);
} // LocalCaptureSpoolingComplete

Listing Ten
#include <FPTypes.h>
#include <CAFShell.h>
#include <MyView.h>

// forward declaration
TBoolean myHandler(TEMEventRecord pEvent, TVoidPtr pData) ;
TBoolean myHandler(TEMEventRecord pEvent, TVoidPtr pData)
{
  TBoolean handled = TRUE ;
    // sample implementation
  return(handled) ;
} // end of myHandler
TVoidPtr entry(void)
{
  TErrCo    err ;
  CAFShell *app = new CAFShell(kAMImagingApp) ;
  MyView   *view = new MyView() ;
  err = app->OpenFW() ;
  app->RegisterSystemHandler(myHandler, NULL) ;

  if(err == kNoErr)
  {
       // miscellaneous initialization
    view = new MyView() ;
    app->OpenView(view) ;
    app->DoEventLoop() ;
    app->CloseFW();
    delete view ;
  }
  delete app ;
  return(NULL) ;
}

Listing Eleven
#define  kMyDoThis     "MyDoThis" 
#define  kMyDoThat     "MyDoThat" 
#define  kMyAbout      "MyAbout" 
MyView::MyView()
{
   // Could create own workspace (container) but using the one supplied.
   // mWorkspace = new CAFWorkSpace() ;
  mItemBar = new CAFItemBar() ;
  mOptionListBox = new CAFListBox();
  mAboutView = new MyAboutView() ;

  SetCommandButton(kCBLeftButton, kMyDoThis ) ;
  SetCommandButton(kCBMiddleButton, kMyDoThat ) ;
  SetCommandButton(kCBRightButton, kMyAbout ) ;
} // end of constructor
MyView::TargetSwitchEnter(TVoid *pData)
{
  int  n, options ;
  CAFActionListItem *nextItem ;
  CAFView * pView ;
    // create a menu
  nextItem = new CAFActionListItem();
  nextItem->SetItemLabel(kMyMenu);
  nextItem->SetActionLabel(kMyDoThis);
  pView = new MyMenuView();
  nextItem->SetView(pView);
  mViewList.AddItem(pView);
  nextItem->SetHelpText((TChar *)NULL, kMyMenuIcon);
  mOptionListBox->AddOption(nextItem);
    // create another menu
  nextItem = new CAFActionListItem();
  nextItem->SetItemLabel(kMyNextMenu);
  nextItem->SetActionLabel(kMyDoThat);
  pView = new MyNextMenuView();
  nextItem->SetView(pView);
  mViewList.AddItem(pView);
  nextItem->SetHelpText((TChar *)NULL, kMyNextMenuIcon);
  mOptionListBox->AddOption(nextItem);
    // more menus
    // Initialize the item bar for this view
  SetItemBar( mItemBar, FALSE) ;
    // set the view parameters
  options = mOptionListBox->GetOptionCount() ;
  for(n = 0 ; n < options ; n++ )
  {
    mOptionListBox->GetOption(n)->SetViewParm(mItemBar) ;
  }
}  // end of TargetSwitchEnter()
TBoolean MyView:HandleEvent( TEMEventRecord *pEvent )
{
  TBoolean handled = FALSE ;
  TBTNDigitaButtonID buttonIndex ;

  if( pEvent->fEvClass == kButtonClassEvent &&
      pEvent->fParams.fButtonEvent.fPosition == kButtonUp )
  {
      // will handle this event
    buttonIndex = pEvent->fParams.fButtonEvent.fButtonIndex ;
    switch(buttonIndex)
    {
       case kDigitaSoftKey1:
           // perform specific operation
           // might be appropriate  to refresh views
         Refresh() ;
         FWRefreshView() ;
         handled = TRUE ;
         break ;
     // other cases . . .
    } // end of switch
  } // end of handling event
  if(!handled)
  {
      // let the parent class handle this event
    handle = CAFBaseView::HandleEvent(pEvent);
  } 
  return(handled) ;
}  // end of HandleEvent()




6


