Add broadcasterctl
This commit is contained in:
parent
b2a8b9c965
commit
7408b1caff
5 changed files with 873 additions and 0 deletions
59
broadcasterctl/BroadcasterAdminController.h
Normal file
59
broadcasterctl/BroadcasterAdminController.h
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* @APPLE_LICENSE_HEADER_START@
|
||||||
|
*
|
||||||
|
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This file contains Original Code and/or Modifications of Original Code
|
||||||
|
* as defined in and that are subject to the Apple Public Source License
|
||||||
|
* Version 2.0 (the 'License'). You may not use this file except in
|
||||||
|
* compliance with the License. Please obtain a copy of the License at
|
||||||
|
* http://www.opensource.apple.com/apsl/ and read it before using this
|
||||||
|
* file.
|
||||||
|
*
|
||||||
|
* The Original Code and all software distributed under the License are
|
||||||
|
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||||
|
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||||
|
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||||
|
* Please see the License for the specific language governing rights and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* @APPLE_LICENSE_HEADER_END@
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
#define kDefaultBroadcasterLoc @"/Applications/QuickTime Broadcaster.app"
|
||||||
|
#define kCantFindBroadcasterError "ERROR: No QuickTime Broadcaster at this location!\n"
|
||||||
|
#define kCantLaunchBroacasterError "ERROR: Couldn't launch QuickTime Broadcaster!\n"
|
||||||
|
#define kBroadcasterNotRunningError "ERROR: QuickTime Broadcaster not running!\n"
|
||||||
|
#define kBadConfigFileError "ERROR: Bad Config File! Quitting QuickTime Broadcaster.\n"
|
||||||
|
#define kCantKillError "ERROR: Can't quit QuickTime Broadcaster. Try running broadcasterctl as root.\n"
|
||||||
|
|
||||||
|
@interface BroadcasterAdminController : NSObject {
|
||||||
|
NSString *myBroadcasterAppPath;
|
||||||
|
id myBroadcasterProxy;
|
||||||
|
BOOL outputXML;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Class methods
|
||||||
|
+ (id)broadcasterAdminController;
|
||||||
|
+ (void)printUsage;
|
||||||
|
|
||||||
|
// Commands (from broadcasterctl args)
|
||||||
|
- (void)launchBroadcaster;
|
||||||
|
- (void)startBroadcaster;
|
||||||
|
- (void)stopBroadcaster;
|
||||||
|
- (void)quitBroadcaster;
|
||||||
|
- (void)printConfig;
|
||||||
|
- (void)printXMLConfig;
|
||||||
|
- (void)printPresets;
|
||||||
|
|
||||||
|
// Accessor methods
|
||||||
|
- (NSString *)myBroadcasterAppPath;
|
||||||
|
- (void)setMyBroadcasterAppPath:(NSString *)newPath;
|
||||||
|
- (id)myBroadcasterProxy;
|
||||||
|
|
||||||
|
@end
|
544
broadcasterctl/BroadcasterAdminController.m
Normal file
544
broadcasterctl/BroadcasterAdminController.m
Normal file
|
@ -0,0 +1,544 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* @APPLE_LICENSE_HEADER_START@
|
||||||
|
*
|
||||||
|
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This file contains Original Code and/or Modifications of Original Code
|
||||||
|
* as defined in and that are subject to the Apple Public Source License
|
||||||
|
* Version 2.0 (the 'License'). You may not use this file except in
|
||||||
|
* compliance with the License. Please obtain a copy of the License at
|
||||||
|
* http://www.opensource.apple.com/apsl/ and read it before using this
|
||||||
|
* file.
|
||||||
|
*
|
||||||
|
* The Original Code and all software distributed under the License are
|
||||||
|
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||||
|
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||||
|
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||||
|
* Please see the License for the specific language governing rights and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* @APPLE_LICENSE_HEADER_END@
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "BroadcasterAdminController.h"
|
||||||
|
#import "BroadcasterRemoteAdmin.h"
|
||||||
|
#include <signal.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "revision.h"
|
||||||
|
|
||||||
|
|
||||||
|
@implementation BroadcasterAdminController
|
||||||
|
|
||||||
|
// Class methods
|
||||||
|
+ (id)broadcasterAdminController
|
||||||
|
{
|
||||||
|
return [[[BroadcasterAdminController alloc] init] autorelease];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)printUsage
|
||||||
|
{
|
||||||
|
NSString *versionString = [NSString stringWithCString:kVersionString];
|
||||||
|
NSString *buildString = [NSString stringWithCString:kBuildString];
|
||||||
|
NSString *usage = [NSString stringWithFormat:@"\nbroadcasterctl %@ (%@)\n\nUsage: broadcasterctl [-b broadcaster-path] [-a audiopreset] [-v videopreset] [-n networkpreset] [-t (audio|video|av)] [-r (record|norecord)] [-f settingsfile] ((config|status|presets|launch|start|stop|restart|quit)\n\n", versionString, buildString];
|
||||||
|
|
||||||
|
printf([usage cString]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray *)otherBroadcasters
|
||||||
|
{
|
||||||
|
NSTask *psTask;
|
||||||
|
NSString *psResult;
|
||||||
|
NSPipe *pipe;
|
||||||
|
NSFileHandle *pipeFileHandle;
|
||||||
|
NSArray *splitResult;
|
||||||
|
NSEnumerator *processEnumerator;
|
||||||
|
id processLine;
|
||||||
|
NSMutableArray *processesToKill = [NSMutableArray array];
|
||||||
|
NSString *processID;
|
||||||
|
NSScanner *processIDScanner;
|
||||||
|
|
||||||
|
psTask = [[[NSTask alloc] init] autorelease];
|
||||||
|
[psTask setLaunchPath:@"/bin/ps"];
|
||||||
|
[psTask setArguments:[NSArray arrayWithObject:@"awx"]];
|
||||||
|
pipe = [NSPipe pipe];
|
||||||
|
[psTask setStandardOutput:pipe];
|
||||||
|
[psTask launch];
|
||||||
|
[psTask waitUntilExit];
|
||||||
|
pipeFileHandle = [pipe fileHandleForReading];
|
||||||
|
psResult = [[[NSString alloc] initWithData:[pipeFileHandle readDataToEndOfFile] encoding:NSASCIIStringEncoding] autorelease];
|
||||||
|
splitResult = [psResult componentsSeparatedByString:@"\n"];
|
||||||
|
processEnumerator = [splitResult objectEnumerator];
|
||||||
|
while (processLine = [processEnumerator nextObject]) {
|
||||||
|
if ([processLine rangeOfString:@"/QuickTime Broadcaster.app"].location != NSNotFound) {
|
||||||
|
processID = [NSString string];
|
||||||
|
processIDScanner = [NSScanner scannerWithString:processLine];
|
||||||
|
[processIDScanner scanUpToString:@" " intoString:&processID];
|
||||||
|
[processesToKill addObject:processID];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [NSArray arrayWithArray:processesToKill];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)killOtherBroadcastersWithSignal:(int)signal
|
||||||
|
{
|
||||||
|
NSArray *otherBroadcasters = [self otherBroadcasters];
|
||||||
|
NSEnumerator *processEnumerator = [otherBroadcasters objectEnumerator];
|
||||||
|
id process;
|
||||||
|
BOOL success = YES;
|
||||||
|
|
||||||
|
while (process = [processEnumerator nextObject]) {
|
||||||
|
if (kill([process intValue], 1) != 0)
|
||||||
|
success = NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
printf(kCantKillError);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)resultForArgument:(NSString *)argName foundError:(BOOL *)err
|
||||||
|
{
|
||||||
|
NSArray *args = [[NSProcessInfo processInfo] arguments];
|
||||||
|
unsigned long argLoc;
|
||||||
|
NSString *result;
|
||||||
|
|
||||||
|
argLoc = [args indexOfObject:argName];
|
||||||
|
if (argLoc == NSNotFound) {
|
||||||
|
*err = NO;
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
argLoc++;
|
||||||
|
|
||||||
|
// if there are no more arguments, something is wrong
|
||||||
|
if ([args count] <= argLoc) {
|
||||||
|
*err = YES;
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = [args objectAtIndex:argLoc];
|
||||||
|
|
||||||
|
// if it starts with a dash, something is wrong
|
||||||
|
if ([result characterAtIndex:0] == '-') {
|
||||||
|
*err = YES;
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
// at this point, all should be fine
|
||||||
|
*err = NO;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)fixPath:(NSString *)path
|
||||||
|
{
|
||||||
|
NSString *pwd = [[[NSProcessInfo processInfo] environment] objectForKey:@"PWD"];
|
||||||
|
NSMutableArray *pathComponents = [NSMutableArray arrayWithArray:[[path stringByExpandingTildeInPath] pathComponents]];
|
||||||
|
if (!pwd)
|
||||||
|
return path;
|
||||||
|
if ([path isAbsolutePath])
|
||||||
|
return path;
|
||||||
|
|
||||||
|
while ([[pathComponents objectAtIndex:0] isEqualToString:@".."]) {
|
||||||
|
[pathComponents removeObjectAtIndex:0];
|
||||||
|
pwd = [pwd stringByDeletingLastPathComponent];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [pwd stringByAppendingPathComponent:[NSString pathWithComponents:pathComponents]];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)init
|
||||||
|
{
|
||||||
|
NSArray *args = [[NSProcessInfo processInfo] arguments];
|
||||||
|
NSString *actionArg = [args lastObject];
|
||||||
|
BOOL err;
|
||||||
|
NSString *argValue;
|
||||||
|
|
||||||
|
self = [super init];
|
||||||
|
|
||||||
|
if ([args count] <= 1) {
|
||||||
|
return nil; // bail
|
||||||
|
}
|
||||||
|
|
||||||
|
// look for an app path argument
|
||||||
|
argValue = [self resultForArgument:@"-b" foundError:&err];
|
||||||
|
if (err)
|
||||||
|
return nil;
|
||||||
|
if (argValue)
|
||||||
|
[self setMyBroadcasterAppPath:[self fixPath:argValue]];
|
||||||
|
else
|
||||||
|
[self setMyBroadcasterAppPath:kDefaultBroadcasterLoc];
|
||||||
|
|
||||||
|
// if we're not telling it to quit, launch the broadcaster if it's not running
|
||||||
|
if ((![actionArg isEqualToString:@"quit"]) && (![self myBroadcasterProxy])) {
|
||||||
|
if ([[self otherBroadcasters] count] > 0) {
|
||||||
|
printf("\nCannot remotely administer the current Broadcaster.");
|
||||||
|
printf("\nUse the 'quit' command to quit the currently running broadcaster.\n\n");
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
if ([actionArg isEqualToString:@"launch"])
|
||||||
|
[self launchBroadcaster];
|
||||||
|
else {
|
||||||
|
printf("\nThe broadcaster isn't running.");
|
||||||
|
printf("\nLaunch it with the 'launch' command.\n\n");
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// config file argument
|
||||||
|
argValue = [self resultForArgument:@"-f" foundError:&err];
|
||||||
|
if (err)
|
||||||
|
return nil;
|
||||||
|
if (argValue && [self myBroadcasterProxy]) {
|
||||||
|
[[self myBroadcasterProxy] setCurrentPresetName:nil ofType:kPresetAudio];
|
||||||
|
[[self myBroadcasterProxy] setCurrentPresetName:nil ofType:kPresetVideo];
|
||||||
|
[[self myBroadcasterProxy] setCurrentPresetName:nil ofType:kPresetNetwork];
|
||||||
|
NS_DURING
|
||||||
|
[[self myBroadcasterProxy] setBroadcastSettingsFile:[self fixPath:argValue]];
|
||||||
|
NS_HANDLER
|
||||||
|
printf("ERROR: Invalid settings file.\n");
|
||||||
|
return self;
|
||||||
|
NS_ENDHANDLER
|
||||||
|
}
|
||||||
|
|
||||||
|
// audio preset argument
|
||||||
|
argValue = [self resultForArgument:@"-a" foundError:&err];
|
||||||
|
if (err)
|
||||||
|
return nil;
|
||||||
|
if (argValue && [self myBroadcasterProxy]) {
|
||||||
|
[[self myBroadcasterProxy] setCurrentPresetName:argValue ofType:kPresetAudio];
|
||||||
|
}
|
||||||
|
|
||||||
|
// video preset argument
|
||||||
|
argValue = [self resultForArgument:@"-v" foundError:&err];
|
||||||
|
if (err)
|
||||||
|
return nil;
|
||||||
|
if (argValue && [self myBroadcasterProxy]) {
|
||||||
|
[[self myBroadcasterProxy] setCurrentPresetName:argValue ofType:kPresetVideo];
|
||||||
|
}
|
||||||
|
|
||||||
|
// network preset argument
|
||||||
|
argValue = [self resultForArgument:@"-n" foundError:&err];
|
||||||
|
if (err)
|
||||||
|
return nil;
|
||||||
|
if (argValue && [self myBroadcasterProxy]) {
|
||||||
|
[[self myBroadcasterProxy] setCurrentPresetName:argValue ofType:kPresetNetwork];
|
||||||
|
}
|
||||||
|
|
||||||
|
// stream type
|
||||||
|
argValue = [self resultForArgument:@"-t" foundError:&err];
|
||||||
|
if (err)
|
||||||
|
return nil;
|
||||||
|
if (argValue && [self myBroadcasterProxy]) {
|
||||||
|
//audio/video/av
|
||||||
|
if ([self myBroadcasterProxy]) {
|
||||||
|
if ([argValue isEqualToString:@"audio"]) {
|
||||||
|
[[self myBroadcasterProxy] setStreamEnabled:YES ofType:kStreamTypeAudio];
|
||||||
|
[[self myBroadcasterProxy] setStreamEnabled:NO ofType:kStreamTypeVideo];
|
||||||
|
}
|
||||||
|
else if ([argValue isEqualToString:@"video"]) {
|
||||||
|
[[self myBroadcasterProxy] setStreamEnabled:NO ofType:kStreamTypeAudio];
|
||||||
|
[[self myBroadcasterProxy] setStreamEnabled:YES ofType:kStreamTypeVideo];
|
||||||
|
}
|
||||||
|
else if ([argValue isEqualToString:@"av"]) {
|
||||||
|
[[self myBroadcasterProxy] setStreamEnabled:YES ofType:kStreamTypeAudio];
|
||||||
|
[[self myBroadcasterProxy] setStreamEnabled:YES ofType:kStreamTypeVideo];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*// recording path argument
|
||||||
|
argValue = [self resultForArgument:@"-p" foundError:&err];
|
||||||
|
if (err)
|
||||||
|
return nil;
|
||||||
|
if (argValue && [self myBroadcasterProxy]) {
|
||||||
|
[[self myBroadcasterProxy] setRecordingPath:argValue];
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// recording argument
|
||||||
|
argValue = [self resultForArgument:@"-r" foundError:&err];
|
||||||
|
if (err)
|
||||||
|
return nil;
|
||||||
|
if (argValue && [self myBroadcasterProxy]) {
|
||||||
|
if ([argValue isEqualToString:@"record"])
|
||||||
|
[[self myBroadcasterProxy] setRecording:YES];
|
||||||
|
else if ([argValue isEqualToString:@"norecord"])
|
||||||
|
[[self myBroadcasterProxy] setRecording:NO];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([actionArg isEqualToString:@"launch"]) {
|
||||||
|
// no need to do anything... it'll launch on its own
|
||||||
|
}
|
||||||
|
else if ([actionArg isEqualToString:@"start"])
|
||||||
|
[self startBroadcaster];
|
||||||
|
else if ([actionArg isEqualToString:@"stop"])
|
||||||
|
[self stopBroadcaster];
|
||||||
|
else if ([actionArg isEqualToString:@"restart"]) {
|
||||||
|
[self stopBroadcaster];
|
||||||
|
[self startBroadcaster];
|
||||||
|
}
|
||||||
|
else if ([actionArg isEqualToString:@"quit"])
|
||||||
|
[self quitBroadcaster];
|
||||||
|
else if (([actionArg isEqualToString:@"config"]) || ([actionArg isEqualToString:@"status"]))
|
||||||
|
[self printConfig];
|
||||||
|
else if ([actionArg isEqualToString:@"xmlstatus"])
|
||||||
|
[self printXMLConfig];
|
||||||
|
else if ([actionArg isEqualToString:@"presets"])
|
||||||
|
[self printPresets];
|
||||||
|
else
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Commands (from broadcasterctl args)
|
||||||
|
|
||||||
|
- (void)launchBroadcaster
|
||||||
|
{
|
||||||
|
NSString *launchPath;
|
||||||
|
NSTask *broadcasterTask;
|
||||||
|
|
||||||
|
launchPath = [[self myBroadcasterAppPath] stringByAppendingPathComponent:@"Contents"];
|
||||||
|
launchPath = [launchPath stringByAppendingPathComponent:@"MacOS"];
|
||||||
|
launchPath = [launchPath stringByAppendingPathComponent:@"QuickTime Broadcaster"];
|
||||||
|
|
||||||
|
if (![[NSFileManager defaultManager] fileExistsAtPath:launchPath]) {
|
||||||
|
printf(kCantFindBroadcasterError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(broadcasterTask = [NSTask launchedTaskWithLaunchPath:launchPath arguments:[NSArray arrayWithObject:@"-noui"]])) {
|
||||||
|
printf(kCantLaunchBroacasterError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (![broadcasterTask isRunning]) {
|
||||||
|
printf(kCantLaunchBroacasterError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (![self myBroadcasterProxy])
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)startBroadcaster
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int state;
|
||||||
|
|
||||||
|
[myBroadcasterProxy startBroadcast];
|
||||||
|
|
||||||
|
for (i = 0; i < 7; i++) {
|
||||||
|
sleep(1);
|
||||||
|
state = [[self myBroadcasterProxy] state];
|
||||||
|
if (state == kBroadcasterStateBroadcasting)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printf(kBadConfigFileError);
|
||||||
|
[self killOtherBroadcastersWithSignal:9];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)stopBroadcaster
|
||||||
|
{
|
||||||
|
if (![self myBroadcasterProxy]) {
|
||||||
|
printf(kBroadcasterNotRunningError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[self myBroadcasterProxy] stopBroadcast];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)quitBroadcaster
|
||||||
|
{
|
||||||
|
if ([self myBroadcasterProxy]) {
|
||||||
|
[[self myBroadcasterProxy] quit];
|
||||||
|
}
|
||||||
|
[self killOtherBroadcastersWithSignal:1];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)printConfig
|
||||||
|
{
|
||||||
|
NSString *settingStringValue;
|
||||||
|
|
||||||
|
if (![self myBroadcasterProxy]) {
|
||||||
|
printf(kBroadcasterNotRunningError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nCurrent State: ");
|
||||||
|
printf([[[self myBroadcasterProxy] stateString] cString]);
|
||||||
|
|
||||||
|
if (settingStringValue = [[self myBroadcasterProxy] broadcastSettingsFile]) {
|
||||||
|
printf("\nBroadcast Settings File: ");
|
||||||
|
printf([settingStringValue cString]);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nAudio Stream: ");
|
||||||
|
if ([[self myBroadcasterProxy] streamEnabled:kStreamTypeAudio])
|
||||||
|
printf("Enabled");
|
||||||
|
else
|
||||||
|
printf("Disabled");
|
||||||
|
|
||||||
|
printf("\nVideo Stream: ");
|
||||||
|
if ([[self myBroadcasterProxy] streamEnabled:kStreamTypeVideo])
|
||||||
|
printf("Enabled");
|
||||||
|
else
|
||||||
|
printf("Disabled");
|
||||||
|
|
||||||
|
printf("\n\nCurrently Selected Presets:");
|
||||||
|
printf("\n Audio: ");
|
||||||
|
if (settingStringValue = [[self myBroadcasterProxy] currentPresetName:kPresetAudio])
|
||||||
|
printf([settingStringValue cString]);
|
||||||
|
else
|
||||||
|
printf("(none)");
|
||||||
|
printf("\n Video: ");
|
||||||
|
if (settingStringValue = [[self myBroadcasterProxy] currentPresetName:kPresetVideo])
|
||||||
|
printf([settingStringValue cString]);
|
||||||
|
else
|
||||||
|
printf("(none)");
|
||||||
|
printf("\n Network: ");
|
||||||
|
if (settingStringValue = [[self myBroadcasterProxy] currentPresetName:kPresetNetwork])
|
||||||
|
printf([settingStringValue cString]);
|
||||||
|
else
|
||||||
|
printf("(none)");
|
||||||
|
|
||||||
|
if ([[self myBroadcasterProxy] recording]) {
|
||||||
|
printf("\n\nRecording to ");
|
||||||
|
settingStringValue = [[self myBroadcasterProxy] recordingPath];
|
||||||
|
if (settingStringValue) {
|
||||||
|
printf([settingStringValue cString]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printf("(default loc)");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("\n\nNot Recording");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)printXMLConfig
|
||||||
|
{
|
||||||
|
NSMutableDictionary *printDict = [NSMutableDictionary dictionary];
|
||||||
|
NSString *settingStringValue;
|
||||||
|
NSMutableDictionary *currentPresets = [NSMutableDictionary dictionary];
|
||||||
|
NSMutableDictionary *presetDict = [NSMutableDictionary dictionary];
|
||||||
|
NSData *plistData;
|
||||||
|
|
||||||
|
if (![self myBroadcasterProxy]) {
|
||||||
|
[printDict setObject:[NSString stringWithCString:kBroadcasterNotRunningError] forKey:@"error"];
|
||||||
|
printf([[printDict description] cString]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// state and settings file
|
||||||
|
[printDict setObject:[[self myBroadcasterProxy] stateString] forKey:@"stateString"];
|
||||||
|
if (!(settingStringValue = [[self myBroadcasterProxy] broadcastSettingsFile]))
|
||||||
|
settingStringValue = @"";
|
||||||
|
[printDict setObject:settingStringValue forKey:@"broadcastSettingsFile"];
|
||||||
|
|
||||||
|
// currently selected presets
|
||||||
|
if (!(settingStringValue = [[self myBroadcasterProxy] currentPresetName:kPresetAudio]))
|
||||||
|
settingStringValue = @"";
|
||||||
|
[currentPresets setObject:settingStringValue forKey:@"audio"];
|
||||||
|
if (!(settingStringValue = [[self myBroadcasterProxy] currentPresetName:kPresetVideo]))
|
||||||
|
settingStringValue = @"";
|
||||||
|
[currentPresets setObject:settingStringValue forKey:@"video"];
|
||||||
|
if (!(settingStringValue = [[self myBroadcasterProxy] currentPresetName:kPresetNetwork]))
|
||||||
|
settingStringValue = @"";
|
||||||
|
[currentPresets setObject:settingStringValue forKey:@"network"];
|
||||||
|
[printDict setObject:currentPresets forKey:@"selectedPresets"];
|
||||||
|
|
||||||
|
// recording options
|
||||||
|
[printDict setObject:[NSNumber numberWithBool:[[self myBroadcasterProxy] recording]] forKey:@"recording"];
|
||||||
|
[printDict setObject:[[self myBroadcasterProxy] recordingPath] forKey:@"recordingPath"];
|
||||||
|
|
||||||
|
// all presets
|
||||||
|
[presetDict setObject:[[self myBroadcasterProxy] presetNameList:kPresetAudio] forKey:@"audio"];
|
||||||
|
[presetDict setObject:[[self myBroadcasterProxy] presetNameList:kPresetVideo] forKey:@"video"];
|
||||||
|
[presetDict setObject:[[self myBroadcasterProxy] presetNameList:kPresetNetwork] forKey:@"network"];
|
||||||
|
[printDict setObject:presetDict forKey:@"allPresets"];
|
||||||
|
|
||||||
|
// print the dictionary
|
||||||
|
plistData = (NSData *)CFPropertyListCreateXMLData(NULL, printDict);
|
||||||
|
|
||||||
|
printf([[[NSString alloc] initWithData:plistData encoding:NSUTF8StringEncoding] cString]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)printPresets
|
||||||
|
{
|
||||||
|
NSArray *allPresets;
|
||||||
|
NSEnumerator *presetEnumerator;
|
||||||
|
id currentPreset;
|
||||||
|
|
||||||
|
if (![self myBroadcasterProxy]) {
|
||||||
|
printf(kBroadcasterNotRunningError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Audio Presets:\n");
|
||||||
|
allPresets = [[self myBroadcasterProxy] presetNameList:kPresetAudio];
|
||||||
|
if ([allPresets count] == 0)
|
||||||
|
printf(" (none)\n");
|
||||||
|
else {
|
||||||
|
presetEnumerator = [allPresets objectEnumerator];
|
||||||
|
while (currentPreset = [presetEnumerator nextObject]) {
|
||||||
|
printf(" ");
|
||||||
|
printf([currentPreset cString]);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("Video Presets:\n");
|
||||||
|
allPresets = [[self myBroadcasterProxy] presetNameList:kPresetVideo];
|
||||||
|
if ([allPresets count] == 0)
|
||||||
|
printf(" (none)\n");
|
||||||
|
else {
|
||||||
|
presetEnumerator = [allPresets objectEnumerator];
|
||||||
|
while (currentPreset = [presetEnumerator nextObject]) {
|
||||||
|
printf(" ");
|
||||||
|
printf([currentPreset cString]);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("Network Presets:\n");
|
||||||
|
allPresets = [[self myBroadcasterProxy] presetNameList:kPresetNetwork];
|
||||||
|
if ([allPresets count] == 0)
|
||||||
|
printf(" (none)\n");
|
||||||
|
else {
|
||||||
|
presetEnumerator = [allPresets objectEnumerator];
|
||||||
|
while (currentPreset = [presetEnumerator nextObject]) {
|
||||||
|
printf(" ");
|
||||||
|
printf([currentPreset cString]);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accessor methods
|
||||||
|
|
||||||
|
- (NSString *)myBroadcasterAppPath
|
||||||
|
{
|
||||||
|
return myBroadcasterAppPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setMyBroadcasterAppPath:(NSString *)newPath
|
||||||
|
{
|
||||||
|
[newPath retain];
|
||||||
|
if (myBroadcasterAppPath)
|
||||||
|
[myBroadcasterAppPath release];
|
||||||
|
myBroadcasterAppPath = newPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)myBroadcasterProxy
|
||||||
|
{
|
||||||
|
if (!myBroadcasterProxy) {
|
||||||
|
myBroadcasterProxy = [[NSConnection rootProxyForConnectionWithRegisteredName:kBroadcasterRemoteAdmin host:nil] retain];
|
||||||
|
}
|
||||||
|
return myBroadcasterProxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
106
broadcasterctl/BroadcasterRemoteAdmin.h
Executable file
106
broadcasterctl/BroadcasterRemoteAdmin.h
Executable file
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* @APPLE_LICENSE_HEADER_START@
|
||||||
|
*
|
||||||
|
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This file contains Original Code and/or Modifications of Original Code
|
||||||
|
* as defined in and that are subject to the Apple Public Source License
|
||||||
|
* Version 2.0 (the 'License'). You may not use this file except in
|
||||||
|
* compliance with the License. Please obtain a copy of the License at
|
||||||
|
* http://www.opensource.apple.com/apsl/ and read it before using this
|
||||||
|
* file.
|
||||||
|
*
|
||||||
|
* The Original Code and all software distributed under the License are
|
||||||
|
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||||
|
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||||
|
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||||
|
* Please see the License for the specific language governing rights and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* @APPLE_LICENSE_HEADER_END@
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
File: BroadcasterRemoteAdmin.h
|
||||||
|
Description: This file contains the BroadcastController protocol. This protocol is
|
||||||
|
used to communicate with QuickTime Broadcaster.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Mach nameserver name
|
||||||
|
#define kBroadcasterRemoteAdmin @"QuickTimeBroadcasterRemoteAdmin"
|
||||||
|
|
||||||
|
// stream types
|
||||||
|
#define kStreamTypeAudio @"audio"
|
||||||
|
#define kStreamTypeVideo @"video"
|
||||||
|
|
||||||
|
// distributed notifications
|
||||||
|
#define kBroadcastQuitNotification @"BroadcastQuitNotification"
|
||||||
|
#define kBroadcastLaunchedNotification @"BraodcastLaunchedNotification"
|
||||||
|
|
||||||
|
// settings
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
kSettingsAudio = 0,
|
||||||
|
kSettingsVideo,
|
||||||
|
kSettingsNetwork
|
||||||
|
};
|
||||||
|
|
||||||
|
// preset types
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
kPresetAudio = 0,
|
||||||
|
kPresetVideo,
|
||||||
|
kPresetNetwork
|
||||||
|
};
|
||||||
|
|
||||||
|
// broadcast state
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
kBroadcasterStateSetup = 0,
|
||||||
|
kBroadcasterStateStartingBroadcast,
|
||||||
|
kBroadcasterStatePrerolling,
|
||||||
|
kBroadcasterStateBroadcasting,
|
||||||
|
kBroadcasterStateStoppingBroadcast
|
||||||
|
};
|
||||||
|
|
||||||
|
// stats
|
||||||
|
#define kBroadcastStatisticCPULoad 'cpul'
|
||||||
|
#define kBroadcastStatisticNumberOfUsersConnected 'nviw'
|
||||||
|
#define kBroadcastStatisticDataRate 'drto'
|
||||||
|
#define kBroadcastStatisticFrameRate 'fps '
|
||||||
|
|
||||||
|
// the protocol used for remote admin (version 1)
|
||||||
|
@protocol BroadcastControllerProtocolVersion1
|
||||||
|
|
||||||
|
// getters
|
||||||
|
- (NSString *)currentPresetName:(short)thePresetType;
|
||||||
|
- (BOOL)recording;
|
||||||
|
- (NSString *)recordingPath;
|
||||||
|
- (NSString *)recordingFileName;
|
||||||
|
- (NSArray *)presetNameList:(short)thePresetType;
|
||||||
|
- (NSString *)broadcastSettingsFile;
|
||||||
|
- (NSString *)stat:(OSType)theType forStreamType:(NSString *)theStreamType;
|
||||||
|
- (UInt32)state;
|
||||||
|
- (NSString *)stateString;
|
||||||
|
- (BOOL)streamEnabled:(NSString *)theStreamType;
|
||||||
|
- (BOOL)streamActive:(NSString *)theStreamType;
|
||||||
|
- (ComponentResult)broadcastError;
|
||||||
|
- (NSString *)broadcastErrorString;
|
||||||
|
|
||||||
|
// setters
|
||||||
|
- (void)setCurrentPresetName:(NSString *)thePresetName ofType:(short)thePresetType;
|
||||||
|
- (void)setRecording:(BOOL)recordOn;
|
||||||
|
- (void)setRecordingPath:(NSString *)thePath;
|
||||||
|
- (void)setRecordingFileName:(NSString *)theFileName;
|
||||||
|
- (void)setBroadcastSettingsFile:(NSString *)thePath;
|
||||||
|
- (void)setStreamEnabled:(BOOL)enable ofType:(NSString *)theStreamType;
|
||||||
|
|
||||||
|
// methods
|
||||||
|
- (void)startBroadcast;
|
||||||
|
- (void)stopBroadcast;
|
||||||
|
- (void)quit;
|
||||||
|
|
||||||
|
@end
|
125
broadcasterctl/broadcasterctl.1
Normal file
125
broadcasterctl/broadcasterctl.1
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
.TH BROADCASTERCTL 1 "August 16, 2002" "Apple Computer, Inc."
|
||||||
|
.SH NAME
|
||||||
|
broadcasterctl \- controller for the QuickTime Broadcaster
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B broadcasterctl
|
||||||
|
[-b broadcaster-path] [-a audiopreset] [-v videopreset] [-n networkpreset]
|
||||||
|
[-t (audio|video|av)] [-r (record|norecord)] [-p recording-path] [-f settingsfile]
|
||||||
|
(config|status|presets|launch|start|stop|restart|quit)
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.I broadcasterctl
|
||||||
|
is a command line tool for controlling the
|
||||||
|
.I QuickTime Broadcaster
|
||||||
|
application. Using
|
||||||
|
.I broadcasterctl
|
||||||
|
you can configure, launch, start, and stop a
|
||||||
|
.SM QuickTime
|
||||||
|
streaming broadcast generated by the
|
||||||
|
.SM MacOS X
|
||||||
|
.I QuickTime Broadcaster
|
||||||
|
application.
|
||||||
|
.PP
|
||||||
|
The
|
||||||
|
.I QuickTime Broadcaster
|
||||||
|
application must be accessable on the local host on which the terminal session is exectuting in order to
|
||||||
|
communicate with that application. (i.e. It will not control a network remote copy of the
|
||||||
|
application.)
|
||||||
|
.SH OPTIONS
|
||||||
|
.PP
|
||||||
|
The following command line options can be invoked with
|
||||||
|
.I broadcasterctl:
|
||||||
|
.TP
|
||||||
|
.B config
|
||||||
|
Sets the configuration of the
|
||||||
|
.I QuickTime Broadcaster
|
||||||
|
application to be that of the currently specified settings file.
|
||||||
|
.TP
|
||||||
|
.B status
|
||||||
|
Returns the current status
|
||||||
|
.I QuickTime Broadcaster
|
||||||
|
application.
|
||||||
|
.TP
|
||||||
|
.B presets
|
||||||
|
Sets the presets of the
|
||||||
|
.I QuickTime Broadcaster
|
||||||
|
application to be that of the currently specified preset values.
|
||||||
|
.TP
|
||||||
|
.B launch
|
||||||
|
Launches the
|
||||||
|
.I QuickTime Broadcaster
|
||||||
|
application.
|
||||||
|
.TP
|
||||||
|
.B start
|
||||||
|
Tells the
|
||||||
|
.I QuickTime Broadcaster
|
||||||
|
application to begin the broadcast.
|
||||||
|
.TP
|
||||||
|
.B stop
|
||||||
|
Tells the
|
||||||
|
.I QuickTime Broadcaster
|
||||||
|
application to stop the broadcast.
|
||||||
|
.TP
|
||||||
|
.B restart
|
||||||
|
Tells the
|
||||||
|
.I QuickTime Broadcaster
|
||||||
|
application to restart the broadcast.
|
||||||
|
.TP
|
||||||
|
.B quit
|
||||||
|
Causes the
|
||||||
|
.I QuickTime Broadcaster
|
||||||
|
application to quit.
|
||||||
|
.TP
|
||||||
|
.BI \-a " audiopreset"
|
||||||
|
Specifies the the current audio preset configuration to be the name given in
|
||||||
|
the
|
||||||
|
.I audiopreset
|
||||||
|
parameter.
|
||||||
|
.TP
|
||||||
|
.BI \-b " broadcaster-path"
|
||||||
|
Specifies the file path to the
|
||||||
|
.I QuickTime Broadcaster
|
||||||
|
application.
|
||||||
|
.TP
|
||||||
|
.BI \-f " settingsfile"
|
||||||
|
Specifies the file path to the broadcast settings file.
|
||||||
|
.TP
|
||||||
|
.BI \-n " networkpreset"
|
||||||
|
Specifies the the current network preset configuration to be the name given in
|
||||||
|
the
|
||||||
|
.I networkpreset
|
||||||
|
parameter.
|
||||||
|
.TP
|
||||||
|
.BI \-p " recording-path"
|
||||||
|
Specifies the file path to record the broadcast to.
|
||||||
|
.TP
|
||||||
|
.BI \-r " (record|norecord)"
|
||||||
|
Controls whether or not the
|
||||||
|
.I QuickTime Broadcaster
|
||||||
|
will record the broadcast to a file as it is broadcasting
|
||||||
|
the stream. Specify
|
||||||
|
.I record
|
||||||
|
to record the broadcast and
|
||||||
|
.I norecord
|
||||||
|
to do nothing. (The default is the
|
||||||
|
.I norecord
|
||||||
|
option.)
|
||||||
|
.TP
|
||||||
|
.BI \-t " (audio|video|av)"
|
||||||
|
Specifies the type of broadcast to be originated. Specifiy
|
||||||
|
.I audio
|
||||||
|
for an audio-only broadcast,
|
||||||
|
.I video
|
||||||
|
for an video-only broadcast, or
|
||||||
|
.I av
|
||||||
|
for a combination audio/video broadcast.
|
||||||
|
.TP
|
||||||
|
.BI \-v " videopreset"
|
||||||
|
Specifies the the current video preset configuration to be the name given in
|
||||||
|
the
|
||||||
|
.I videopreset
|
||||||
|
parameter.
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
QuickTimeStreamingServer(1), ps(1), kill(1)
|
||||||
|
.SH LIMITATIONS
|
||||||
|
Only one audio, video, or audio/video session can be controlled per invokation of
|
||||||
|
.I broadcasterctl.
|
39
broadcasterctl/broadcasterctl_main.m
Normal file
39
broadcasterctl/broadcasterctl_main.m
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* @APPLE_LICENSE_HEADER_START@
|
||||||
|
*
|
||||||
|
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This file contains Original Code and/or Modifications of Original Code
|
||||||
|
* as defined in and that are subject to the Apple Public Source License
|
||||||
|
* Version 2.0 (the 'License'). You may not use this file except in
|
||||||
|
* compliance with the License. Please obtain a copy of the License at
|
||||||
|
* http://www.opensource.apple.com/apsl/ and read it before using this
|
||||||
|
* file.
|
||||||
|
*
|
||||||
|
* The Original Code and all software distributed under the License are
|
||||||
|
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||||
|
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||||
|
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||||
|
* Please see the License for the specific language governing rights and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* @APPLE_LICENSE_HEADER_END@
|
||||||
|
*/
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "BroadcasterAdminController.h"
|
||||||
|
|
||||||
|
int main (int argc, const char * argv[]) {
|
||||||
|
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
|
||||||
|
BroadcasterAdminController *mainController;
|
||||||
|
|
||||||
|
mainController = [BroadcasterAdminController broadcasterAdminController];
|
||||||
|
|
||||||
|
if (!mainController)
|
||||||
|
[BroadcasterAdminController printUsage];
|
||||||
|
|
||||||
|
[pool release];
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue