QTBroadcast.c

//////////
//
//  File:       QTBroadcast.c
//
//  Contains:   Code for broadcasting QuickTime movies.
//
//  Written by: Tim Monroe
//
//  Copyright:  © 2001 by Apple Computer, Inc., all rights reserved.
//
//  Change History (most recent first):
//
//     <1>      04/11/01    rtm     first file
//
//////////
 
//////////
//
// header files
//
//////////
 
#include "QTBroadcast.h"
 
 
//////////
//
// global variables
//
//////////
 
#if TARGET_OS_MAC
extern                          gAppInForeground;
extern                          gHasNewDialogCalls;
#endif
 
QTSPresentation                 gPresentation = kQTSInvalidPresentation;
QTSNotificationUPP              gNotificationUPP = NULL;
DialogPtr                       gMonitor = NULL;
UserItemUPP                     gMonitorUserItemProcUPP = NULL;         // UPP to our custom dialog user item procedure
Boolean                         gBroadcasting = false;
 
 
//////////
//
// QTBC_Init
// Initialize application for broadcasting.
//
//////////
 
OSErr QTBC_Init (void)
{
    OSErr                   myErr = noErr;
 
    // allocate global storage
    gNotificationUPP = (QTSNotificationUPP)NewQTSNotificationUPP(QTBC_NotificationProc);
    if (gNotificationUPP == NULL) {
        myErr = paramErr;
        goto bail;
    }
    
    gMonitorUserItemProcUPP = NewUserItemUPP(QTBC_UserItemProcedure);
    if (gMonitorUserItemProcUPP == NULL) {
        myErr = paramErr;
        goto bail;
    }
    
    // open the monitor window
    gMonitor = QTBC_CreateMonitorWindow();
    if (gMonitor == NULL) {
        myErr = memFullErr;
        goto bail;
    }
    
bail:
    // if an error occurred, clean up
    if (myErr != noErr)
        QTBC_Stop();
    
    return(myErr);
}
 
 
//////////
//
// QTBC_Stop
// Shut down the application's broadcasting support.
//
//////////
 
void QTBC_Stop (void)
{
    // deallocate any global storage
    if (gNotificationUPP != NULL) {
        DisposeQTSNotificationUPP(gNotificationUPP);
        gNotificationUPP = NULL;
    }
    
    if (gMonitorUserItemProcUPP != NULL) {
        DisposeUserItemUPP(gMonitorUserItemProcUPP);
        gMonitorUserItemProcUPP = NULL;
    }
 
    // close the monitor window
    if (gMonitor != NULL)
        DisposeDialog(gMonitor);
}
 
 
//////////
//
// QTBC_SetupPresentation
// Set up our presentation.
//
//////////
 
OSErr QTBC_SetupPresentation (void)
{
    QTSNewPresentationParams    *myPresParamsPtr = NULL;
    QTSMediaParams              *myMediaParamsPtr = NULL;
    FSSpec                      myFSSpec;
    OSType                      myTypeList[] = {kQTFileTypeText};
    short                       myNumTypes = 1;
    QTFrameFileFilterUPP        myFileFilterUPP = NULL;
    OSErr                       myErr = noErr;
    
#if TARGET_OS_MAC
    myNumTypes = 0;
#endif
 
    // create a new presentation parameters structure
    myPresParamsPtr = (QTSNewPresentationParams *)NewPtrClear(sizeof(QTSNewPresentationParams));
    if (myPresParamsPtr == NULL) {
        myErr = MemError();
        goto bail;
    }
    
    // create a new media parameters structure
    myMediaParamsPtr = (QTSMediaParams *)NewPtrClear(sizeof(QTSMediaParams));
    if (myMediaParamsPtr == NULL) {
        myErr = MemError();
        goto bail;
    }
    
    // initialize the media parameters to default values
    myErr = QTSInitializeMediaParams(myMediaParamsPtr);
    if (myErr != noErr)
        goto bail;
 
    // elicit an SDP file from the user
    myFileFilterUPP = QTFrame_GetFileFilterUPP((ProcPtr)QTFrame_FilterFiles);
    myErr = QTFrame_GetOneFileWithPreview(myNumTypes, (QTFrameTypeListPtr)myTypeList, &myFSSpec, myFileFilterUPP);
    if (myErr != noErr)
        goto bail;
 
    // start broadcasting from an SDP file
    myPresParamsPtr->dataType = kQTSFileDataType;
    myPresParamsPtr->data = &myFSSpec;
    myPresParamsPtr->dataLength = sizeof(myFSSpec);
    
    // set the presentation flags: use Sequence Grabber, don't display blue Q movie, and send data
    myPresParamsPtr->flags = kQTSAutoModeFlag | kQTSDontShowStatusFlag | kQTSSendMediaFlag;
 
    myPresParamsPtr->timeScale = 0;
    myPresParamsPtr->mediaParams = myMediaParamsPtr;
    
    // fill these in to get status notifications
    myPresParamsPtr->notificationProc = gNotificationUPP;
    myPresParamsPtr->notificationRefCon = 0L;               // no refcon yet
    
    // define the display size and the default transmission size
    myPresParamsPtr->mediaParams->v.width = Long2Fix(176);
    myPresParamsPtr->mediaParams->v.height = Long2Fix(144);
    
    TranslateMatrix(&(myPresParamsPtr->mediaParams->v.matrix), Long2Fix(10), Long2Fix(10));
    
    // set the window that Sequence Grabber will draw into
    myPresParamsPtr->mediaParams->v.gWorld = GetDialogPort(gMonitor);
    myPresParamsPtr->mediaParams->v.gdHandle = NULL;
    
    // create a new presentation
    myErr = QTSNewPresentation(myPresParamsPtr, &gPresentation);
    if (myErr != noErr)
        goto bail;
    
    myErr = QTSPresPreview(gPresentation, kQTSAllStreams, NULL, kQTSNormalForwardRate, 0);
 
bail:
    if (myPresParamsPtr != NULL)
        DisposePtr((Ptr)myPresParamsPtr);
 
    if (myMediaParamsPtr != NULL)
        DisposePtr((Ptr)myMediaParamsPtr);
    
    if (myFileFilterUPP != NULL)
        DisposeNavObjectFilterUPP(myFileFilterUPP);
 
    return(myErr);
}
 
 
//////////
//
// QTBC_StartBroadcasting
// Start broadcasting.
//
//////////
 
OSErr QTBC_StartBroadcasting (void)
{
    // stop the preview
    QTSPresPreview(gPresentation, kQTSAllStreams, NULL, kQTSStoppedRate, 0);
 
    return(QTSPresPreroll(gPresentation, kQTSAllStreams, 0, (Fixed)kQTSNormalForwardRate, 0L));
}
 
 
//////////
//
// QTBC_PauseBroadcasting
// Pause broadcasting.
//
//////////
 
OSErr QTBC_PauseBroadcasting (void)
{
    OSErr       myErr = noErr;
    
    myErr = QTSPresStop(gPresentation, kQTSAllStreams, 0L);
    if (myErr != noErr)
        goto bail;
 
    // restart the preview
    myErr = QTSPresPreview(gPresentation, kQTSAllStreams, NULL, kQTSNormalForwardRate, 0);
 
bail:
    return(myErr);
}
 
 
//////////
//
// QTBC_StopBroadcasting
// Stop broadcasting.
//
//////////
 
OSErr QTBC_StopBroadcasting (void)
{
    OSErr       myErr = noErr;
    
    if (gPresentation != kQTSInvalidPresentation) {
        myErr = QTSPresStop(gPresentation, kQTSAllStreams, 0L);
        
        if (myErr != noErr)
            myErr = QTSDisposePresentation(gPresentation, 0L);
            
        gPresentation = kQTSInvalidPresentation;
    }
    
    return(myErr);
}
 
 
//////////
//
// QTBC_NotificationProc
// Handle notification messages.
//
//////////
 
static PASCAL_RTN ComponentResult QTBC_NotificationProc (ComponentResult theErr, OSType theNotificationType, void *theNotificationParams, void *theRefCon)
{
#pragma unused(theErr, theNotificationParams, theRefCon)
    QTSPresentation     myPresentation = kQTSInvalidPresentation;
    ComponentResult     myErr = noErr;
 
    switch (theNotificationType) {
    
        case kQTSNewPresentationNotification:
            // when we get this notification, the presentation has been created and is sent to us in theNotificationParams;
            // if we needed it, we could retrieve it as follows:
            myPresentation = (QTSPresentation)theNotificationParams;
            break;
 
        case kQTSPrerollAckNotification:
            myErr = QTSPresStart(gPresentation, kQTSAllStreams, 0L);
            break;
    
        case kQTSStartAckNotification:
        case kQTSStopAckNotification:
            break;
    
        default:
            break;
    }
    
    return(myErr);
}
 
 
//////////
//
// QTBC_CreateMonitorWindow
// Create and display the monitor window.
//
//////////
 
DialogPtr QTBC_CreateMonitorWindow (void)
{
    DialogPtr   myDialog = NULL;
    
    myDialog = GetNewDialog(kMonitorDLOGID, NULL, (WindowPtr)-1L);
 
    if (myDialog != NULL) {
        short       myItemKind;
        Handle      myItemHandle = NULL;
        Rect        myItemRect;
        
        MacSetPort(GetDialogPort(myDialog));
    
        // set the user item drawing procedure
        GetDialogItem(myDialog, kMonitorUserItemID, &myItemKind, &myItemHandle, &myItemRect);                       
        SetDialogItem(myDialog, kMonitorUserItemID, myItemKind, (Handle)gMonitorUserItemProcUPP, &myItemRect);
    
        MacShowWindow(GetDialogWindow(myDialog));
        QTBC_UserItemProcedure(myDialog, kMonitorUserItemID);
    }
    
    return(myDialog);
}
 
 
//////////
//
// QTBC_UserItemProcedure
// Draw the user item in the monitor window.
//
//////////
 
PASCAL_RTN void QTBC_UserItemProcedure (DialogPtr theDialog, short theItem)
{
    short                   myItemKind;
    Handle                  myItemHandle = NULL;
    Rect                    myItemRect;
    GrafPtr                 mySavedPort;
    OSErr                   myErr = noErr;
    
    GetPort(&mySavedPort);
    MacSetPort(GetDialogPort(theDialog));
    
    if (theItem != kMonitorUserItemID)
        goto bail;
 
    // draw a frame around the user item rectangle
    GetDialogItem(theDialog, kMonitorUserItemID, &myItemKind, &myItemHandle, &myItemRect);
    InsetRect(&myItemRect, -1, -1);
    MacFrameRect(&myItemRect);
 
    // enable the Start/Stop button in the monitor window
    GetDialogItem(theDialog, kMonitorButtonID, &myItemKind, &myItemHandle, &myItemRect);
    if (myItemHandle != NULL) {
        if (gPresentation == kQTSInvalidPresentation)
            HiliteControl((ControlHandle)myItemHandle, 255);
        else
            HiliteControl((ControlHandle)myItemHandle, 0);
    }
 
bail:
    MacSetPort(mySavedPort);
}
 
 
//////////
//
// QTBC_HandleMonitorWindowEvents
// Handle events for the monitor window.
//
//////////
 
void QTBC_HandleMonitorWindowEvents (DialogPtr theDialog, DialogItemIndex theItemHit)
{
    short           myItemKind;
    Handle          myItemHandle = NULL;
    Rect            myItemRect;
 
    if ((theDialog == gMonitor) && (theItemHit == kMonitorButtonID)) {
    
        GetDialogItem(theDialog, kMonitorButtonID, &myItemKind, &myItemHandle, &myItemRect);                        
        if (gBroadcasting) {
            QTBC_PauseBroadcasting();
            SetControlTitle((ControlHandle)myItemHandle, "\pStart");
        } else {
            QTBC_StartBroadcasting();
            SetControlTitle((ControlHandle)myItemHandle, "\pPause");
        }
        
        gBroadcasting = !gBroadcasting;
    }
}