Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
sources/UsherNew.c
/* |
File: UsherNew.c |
Copyright: © 2000-2001 by Apple Computer, Inc., all rights reserved. |
*/ |
#include <ConditionalMacros.h> |
#include <Files.h> |
#include <Resources.h> |
#include <TextUtils.h> |
#include <ToolUtils.h> |
#include <stdlib.h> |
#include <string.h> |
#include <QuicktimeComponents.h> |
#include <MoviesFormat.h> |
#include <Movies.h> |
#include <QuickTimeStreaming.h> |
#include <QTStreamingComponents.h> |
#include "AppSupport.h" |
#include "QTSSampleCodeUtils.h" |
#include "UsherBroadcast.h" |
#include "UsherCommands.h" |
#include "UsherNew.h" |
#include "WindowSupport.h" |
// ----- source handlers we know about ----- |
#include "MovieSourcing.h" |
// --------------------------------------------------------------------------- |
// D E F I N I T I O N S |
// --------------------------------------------------------------------------- |
struct UsherSettingsStuff { |
Boolean doSourcerSwitching; |
// stored movie settings |
Boolean doStoredMovies; |
MovieSourcingSettings movieSourcingSettings; |
UInt16 width; |
UInt16 height; |
Boolean haveSpatialSettings; |
SCSpatialSettings spatialSettings; |
Boolean haveTemporalSettings; |
SCTemporalSettings temporalSettings; |
Boolean haveDataRateSettings; |
SCDataRateSettings dataRateSettings; |
}; |
typedef struct UsherSettingsStuff UsherSettingsStuff; |
// --------------------------------------------------------------------------- |
// P R O T O T Y P E S |
// --------------------------------------------------------------------------- |
static OSErr Usher_GetBroadcastSettingsFromFile(const FSSpec *inFileSpec, |
UsherSettingsStuff *outSettingsStuff); |
static OSErr Usher_MakeSourceHandlersFromSettings(UsherBroadcast *inBroadcast, |
UsherSettingsStuff *inSettingsStuff, SourceMediaParams *inMediaParams); |
static OSErr GetFileExtension(const FSSpec *inSpec, OSType *outExtension); |
static OSErr Usher_DoXMLStuff(Handle inDataHandle, UsherSettingsStuff *outSettingsStuff); |
static pascal ComponentResult UsherXML_StartElementHandler(const char *inName, |
const char **inAttributes, long inRefcon); |
static ComponentResult UsherXML_ParseDimensions(UsherSettingsStuff *inSettingsStuff, const char **inAttributes); |
// --------------------------------------------------------------------------- |
// Usher_NewBroadcastFromFile |
// --------------------------------------------------------------------------- |
OSErr Usher_NewBroadcastFromFile(const FSSpec *inFileSpec, OSType inWindowType) |
{ |
OSErr err = noErr; |
WindowPtr window = NULL; |
UsherBroadcast *broadcast = 0; |
UsherSettingsStuff settingsStuff; |
SourceMediaParams sourceMediaParams; |
OSErr tempErr; |
Boolean addedWindow = false; |
Boolean useLargeSize = false; |
memset(&settingsStuff, 0, sizeof(settingsStuff)); |
EXITIFERR( err = Usher_GetBroadcastSettingsFromFile(inFileSpec, &settingsStuff) ); |
if ((settingsStuff.width != 0) && (settingsStuff.height != 0)) { |
if ((settingsStuff.width > 176) || (settingsStuff.height > 144)) { |
useLargeSize = true; |
} |
} |
memset(&sourceMediaParams, 0, sizeof(sourceMediaParams)); |
EXITIFERR( err = WindowSupport_NewWindowOfType(inWindowType, useLargeSize, &window) ); |
// if there's an error in here, the presentation will take care |
// of disposing the window |
tempErr = WindowSupport_HandleMessage(window, kMessage_GetPresBox, &sourceMediaParams.localDisplayRect); |
sourceMediaParams.gWorld = GetWindowPort(window); |
sourceMediaParams.gdHandle = GetMainDevice(); //@@@ |
EXITIFERR( err = UsherBroadcast_NewFromFile(inFileSpec, sourceMediaParams.gWorld, |
sourceMediaParams.gdHandle, &sourceMediaParams.localDisplayRect, &broadcast) ); |
EXITIFERR( err = Usher_MakeSourceHandlersFromSettings(broadcast, &settingsStuff, &sourceMediaParams) ); |
EXITIFERR( err = WindowSupport_HandleMessage(window, kMessage_SetUsherBroadcast, (void*)broadcast) ); |
UsherBroadcast_AddWindow(broadcast, window); |
addedWindow = true; |
MacShowWindow(window); |
exit: |
if (err != noErr) { |
char tempString[256]; |
if (broadcast != NULL) { |
UsherBroadcast_Dispose(broadcast); |
} |
if (!addedWindow && (window != NULL)) { |
WindowSupport_CloseWindow(window); |
} |
CopyPToCStr(inFileSpec->name, tempString); |
ProcessUserMessage(kProcessMessageFlag_Log | kProcessMessageFlag_ShowDialog, |
"Error (%ld) creating new broadcast from file '%s'", err, tempString); |
} |
return err; |
} |
// --------------------------------------------------------------------------- |
// Usher_MakeSourceHandlersFromSettings |
// --------------------------------------------------------------------------- |
static OSErr Usher_MakeSourceHandlersFromSettings(UsherBroadcast *inBroadcast, |
UsherSettingsStuff *inSettingsStuff, SourceMediaParams *inMediaParams) |
{ |
OSErr err = noErr; |
void *sourceHandler = NULL; |
QTSPresentation presentation; |
#define kDefaultMoviePlayInterval (30 * 60) |
#define kDefaultPushFramePlayInterval (5 * 60) |
presentation = UsherBroadcast_GetQTSPresentation(inBroadcast); |
if (inSettingsStuff->doStoredMovies) { |
EXITIFERR( err = MovieSourcing_New(presentation, inMediaParams, &inSettingsStuff->movieSourcingSettings, (MovieSourcing**)&sourceHandler) ); |
} |
if (sourceHandler != NULL) { |
EXITIFERR( err = UsherBroadcast_AddSourceHandler(inBroadcast, sourceHandler) ); |
} |
exit: |
return err; |
} |
// --------------------------------------------------------------------------- |
// Usher_GetBroadcastSettingsFromFile |
// --------------------------------------------------------------------------- |
static OSErr Usher_GetBroadcastSettingsFromFile(const FSSpec *inFileSpec, |
UsherSettingsStuff *outSettingsStuff) |
{ |
OSErr err = noErr; |
OSErr tempErr = noErr; |
Handle dataHandle = NULL; |
Ptr dataPtr; |
UInt32 maxLength; |
const char *current; |
const char *more; |
#define kMaxContentsToScan (5*1024) |
memset(outSettingsStuff, 0, sizeof(UsherSettingsStuff)); |
EXITIFERR( tempErr = GetFileContents(inFileSpec, kMaxContentsToScan, &dataHandle, NULL) ); |
HLock(dataHandle); |
dataPtr = *dataHandle; |
maxLength = GetHandleSize(dataHandle); |
#define kSendPresSDPString_DoStoredMovies "a=x-usher-play-stored-movies" |
#define kSendPresSDPString_LoopMovie "a=x-usher-loop-movie" |
#define kSendPresSDPString_MovieFolder "a=x-usher-movie-folder:" |
#define kSendPresSDPString_MovieSelection "a=x-usher-movie-selection:" |
#define kSendPresMovieSelectionParams_Random "random" |
#define kSendPresMovieSelectionParams_InOrder "inorder" |
// ----- stored movie settings |
current = ScanToString(dataPtr, maxLength, kSendPresSDPString_DoStoredMovies, strlen(kSendPresSDPString_DoStoredMovies)); |
if ((current != NULL) && |
( (current == dataPtr) || IsEOLChar(current[-1]) ) ) { |
outSettingsStuff->doStoredMovies = true; |
current = ScanToString(dataPtr, maxLength, kSendPresSDPString_LoopMovie, strlen(kSendPresSDPString_LoopMovie)); |
if ((current != NULL) && ((current == dataPtr) || IsEOLChar(current[-1]))) { |
outSettingsStuff->movieSourcingSettings.loop = true; |
} |
current = ScanToString(dataPtr, maxLength, kSendPresSDPString_MovieFolder, strlen(kSendPresSDPString_MovieFolder)); |
if ((current != NULL) && ((current == dataPtr) || IsEOLChar(current[-1]))) { |
// the next thing is the folder path |
current += strlen(kSendPresSDPString_MovieFolder); |
more = GetLineEnd(current, maxLength - (current-dataPtr)); |
if ((more != NULL) && (more != current)) { |
// the folder path is relative to the app; aliases are ok |
} |
} |
current = ScanToString(dataPtr, maxLength, kSendPresSDPString_MovieSelection, strlen(kSendPresSDPString_MovieSelection)); |
if ((current != NULL) && ((current == dataPtr) || IsEOLChar(current[-1]))) { |
current += strlen(kSendPresSDPString_MovieSelection); |
more = GetLineEnd(current, maxLength - (current-dataPtr)); |
if ((more != NULL) && (more != current)) { |
// this must match |
if (StartsWith(more, maxLength - (more-dataPtr), kSendPresMovieSelectionParams_Random, strlen(kSendPresMovieSelectionParams_Random))) { |
outSettingsStuff->movieSourcingSettings.selectRandomly = true; |
} |
} |
} |
} |
{ |
OSType extension = 0; |
if (GetFileExtension(inFileSpec, &extension) == noErr) { |
if ((extension == 'xml ') || (extension == 'XML ')) { |
Usher_DoXMLStuff(dataHandle, outSettingsStuff); |
} |
} |
} |
exit: |
DisposeHandle(dataHandle); |
return err; |
} |
#pragma mark - |
//----------------------------------------------------------------------------- |
// GetFileExtension |
//----------------------------------------------------------------------------- |
static OSErr GetFileExtension(const FSSpec *inSpec, OSType *outExtension) |
{ |
UInt32 current; |
UInt32 length; |
Boolean foundPeriod = false; |
OSErr err = paramErr; |
#define kPeriodChar '.' |
#define kSpacePadding 0x20202020 |
// parse backwards until you get to a period |
*outExtension = 0; |
length = inSpec->name[0]; |
current = length; |
while (current > 0) { |
if (inSpec->name[current] == kPeriodChar) { |
// found a period - stop |
foundPeriod = true; |
break; |
} |
--current; |
} |
// if you found one and it was within 5 of the end of the name, you |
// have an extension |
if (foundPeriod) { |
if (current >= length - sizeof(OSType)) { |
*outExtension = kSpacePadding; |
BlockMoveData(inSpec->name + current + 1, |
outExtension, (long)(length-current)); |
*outExtension = EndianU32_NtoB( *outExtension ); |
err = noErr; |
} |
} |
return err; |
} |
static QTSNotificationUPP sXMLStartElementUPP = NULL; |
// --------------------------------------------------------------------------- |
// Usher_DoXMLStuff |
// --------------------------------------------------------------------------- |
static OSErr Usher_DoXMLStuff(Handle inDataHandle, UsherSettingsStuff *outSettingsStuff) |
{ |
OSErr err = noErr; |
ComponentInstance xmlParser = 0; |
Handle hdataref = NULL; |
if (sXMLStartElementUPP == NULL) { |
sXMLStartElementUPP = (StartElementHandlerUPP)NewStartElementHandlerUPP(UsherXML_StartElementHandler); |
} |
EXITIFERR( err = OpenADefaultComponent(xmlParseComponentType, xmlParseComponentSubType, &xmlParser) ); |
XMLParseSetEventParseRefCon(xmlParser, (long)(outSettingsStuff)); |
XMLParseSetStartElementHandler(xmlParser, sXMLStartElementUPP); |
hdataref = NewHandle(sizeof(HandleDataRefRecord)); |
if (hdataref != NULL) { |
(**((HandleDataRef)hdataref)).dataHndl = inDataHandle; |
EXITIFERR( err = XMLParseDataRef(xmlParser, hdataref, |
HandleDataHandlerSubType, xmlParseFlagEventParseOnly, NULL) ); |
} |
exit: |
if (xmlParser != 0) { |
CloseComponent(xmlParser); |
} |
if (hdataref != NULL) { |
DisposeHandle(hdataref); |
} |
return err; |
} |
// --------------------------------------------------------------------------- |
// XMLStreamImport_StartElementHandler |
// --------------------------------------------------------------------------- |
static pascal ComponentResult UsherXML_StartElementHandler(const char *inName, |
const char **inAttributes, long inRefcon) |
{ |
ComponentResult err = noErr; |
UsherSettingsStuff *settingsStuff = (UsherSettingsStuff*)inRefcon; |
long nameLength; |
#define kXMLElement_Dimensions "dimensions" |
#define kXMLElement_Compression "compression" |
nameLength = strlen(inName); |
if (EqualChars(kXMLElement_Dimensions, strlen(kXMLElement_Dimensions), inName, nameLength)) { |
err = UsherXML_ParseDimensions(settingsStuff, inAttributes); |
} |
exit: |
return err; |
} |
// --------------------------------------------------------------------------- |
// UsherXML_ParseDimensions |
// --------------------------------------------------------------------------- |
static ComponentResult UsherXML_ParseDimensions(UsherSettingsStuff *inSettingsStuff, const char **inAttributes) |
{ |
ComponentResult err = noErr; |
UInt32 index; |
const char *attribute; |
const char *value; |
long attrLength; |
#define kXMLAttr_Width "width" |
#define kXMLAttr_Height "height" |
index = 0; |
while (inAttributes[index] != NULL) { |
attribute = inAttributes[index]; |
value = inAttributes[index+1]; |
attrLength = strlen(attribute); |
if (EqualChars(kXMLAttr_Width, strlen(kXMLAttr_Width), attribute, attrLength)) { |
inSettingsStuff->width = atol(value); |
} else if (EqualChars(kXMLAttr_Height, strlen(kXMLAttr_Height), attribute, attrLength)) { |
inSettingsStuff->height = atol(value); |
} else { |
//DEBUGF(("XMLStreamImport_ParseRTPMap $%.8x-unhandled '%s'", inInfo, attribute)); |
} |
index += 2; |
} |
exit: |
return err; |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14