📄 mp4playercontroller.m
字号:
#import "MP4PlayerController.h"
#import <Foundation/NSTimer.h>
/*
* Objective-C++ controller object to interface with the mpeg4ip CPlayerSession model object.
*
* We have to wrap the C++ CPlayerSession object in a set of C-callable functions
* (see player_session_wrap.h) because Objective-C++ is nowhere to be found these
* days. It would be much cooler if we could just use it directly.
*/
@implementation MP4PlayerController
- (id)init
{
self = [super init];
player = 0;
state = CLOSED;
// XXX: This stuff doesn't actually work. I need to initialize my stuff after
// de-archiving, but in some other method... what's it called?
return self;
}
- (void)stateHasChanged
{
if (state == CLOSED) {
[volume setEnabled:NO];
[time setEnabled:NO];
[playButton setEnabled:NO];
[pauseButton setEnabled:NO];
[stopButton setEnabled:NO];
[firstLine setObjectValue:@"mpeg4ip"];
[secondLine setObjectValue:@"version 0.7"];
}
else {
[firstLine setObjectValue:filename];
[volume setEnabled:YES];
[time setEnabled:YES];
if ((CPS_get_session_state(player) != SESSION_BUFFERING) && (!needToSeek))
[time setDoubleValue:CPS_get_playing_time(player)];
[time setMaxValue:CPS_get_max_time(player)];
switch (state) {
case PLAYING:
[secondLine setObjectValue:@"Playing"];
[playButton setEnabled:NO];
[pauseButton setEnabled:YES];
[stopButton setEnabled:YES];
break;
default:
[playButton setEnabled:YES];
[pauseButton setEnabled:NO];
if ([time doubleValue] == 0.0) {
[stopButton setEnabled:NO];
[secondLine setObjectValue:@"Stopped"];
}
else {
[stopButton setEnabled:YES];
[secondLine setObjectValue:@"Paused"];
}
break;
}
}
}
- (IBAction)adjustVolume:(id)sender
{
float x = [volume floatValue];
if (player)
CPS_set_audio_volume(player, x);
}
- (IBAction)seek:(id)sender
{
NSLog(@"seek: %f", [time doubleValue]);
if (state == PLAYING) {
assert(player != nil);
CPS_pause_all_media(player);
CPS_play_all_media(player, ([time doubleValue] == 0.0),
[time doubleValue]);
}
else {
needToSeek = YES;
}
[self stateHasChanged];
}
- (IBAction)open:(id)sender
{
int result;
NSArray *fileTypes;
NSOpenPanel *oPanel;
// Close first if already open
if (player != 0) {
[self close:sender];
}
// Ask user what to open
NSLog(@"getting file name . . .");
fileTypes = [NSArray arrayWithObject:@"td"];
oPanel = [NSOpenPanel openPanel];
result = [oPanel runModalForDirectory:nil file:nil types:nil];
if (result != NSOKButton)
return;
filename = [oPanel filename];
[self doOpen];
}
- (IBAction)openURL:(id)sender
{
[[openURLPanel windowController] showWindow:sender];
}
- (IBAction)doOpenURL:(id)sender
{
[[openURLPanel windowController] close];
filename = [urlComboBox objectValue];
(void) [urlComboBox removeItemWithObjectValue:filename];
[urlComboBox insertItemWithObjectValue:filename atIndex:0];
[self doOpen];
}
- (void)doOpen
{
int result;
char* errmsg;
if (!master_queue)
master_queue = new_CMQ();
if (!master_sem)
master_sem = SDL_CreateSemaphore(0);
player = new_CPS(master_queue, master_sem, "MPEG-4 Player");
result = parse_name_for_c_session(player, [filename lossyCString], &errmsg);
if (result < 0) {
NSString* errstr = [NSString stringWithCString:errmsg];
NSLog(@"Name parse failed: %s", errmsg);
CPS_destroy(player);
NSRunAlertPanel(@"Cannot open file", errstr, nil, nil, nil);
return;
}
/* Cool beans, we have a file open. */
/* FIXME: Get screen location from this window somehow. */
CPS_set_screen_location(player, 100, 100);
CPS_set_screen_size(player, screenSize, 0);
[time setMaxValue:CPS_get_max_time(player)];
[time setDoubleValue:0];
[self adjustVolume:nil];
if (CPS_session_is_seekable(player))
[time setEnabled:YES];
else
[time setEnabled:NO];
state = NOT_PLAYING;
syncThreadStarted = NO;
[self stateHasChanged];
}
- (IBAction)pause:(id)sender
{
session_state_t pst;
assert(state == PLAYING);
assert(player != nil);
pst = CPS_get_session_state(player);
if (CPS_get_session_state(player) == SESSION_DONE) {
// Nobody else noticed this yet.
state = NOT_PLAYING;
return;
}
assert(pst != SESSION_PAUSED);
CPS_pause_all_media(player);
state = NOT_PLAYING;
[self stateHasChanged];
}
- (IBAction)play:(id)sender
{
session_state_t pst;
double newtime;
static BOOL timerStarted = NO;
assert(player != nil);
assert(state == NOT_PLAYING);
if (!timerStarted) {
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(stateHasChanged) userInfo:nil repeats:YES];
timerStarted = YES;
}
pst = CPS_get_session_state(player);
assert(pst == SESSION_PAUSED || pst == SESSION_DONE);
if (!syncThreadStarted) {
NSLog(@"setting up sync thread . . .");
CPS_set_up_sync_thread(player);
syncThreadStarted = YES;
}
if (needToSeek) {
NSLog(@"Need to seek");
newtime = [time doubleValue];
needToSeek = NO;
}
else {
NSLog(@"Don't need to seek");
newtime = CPS_get_playing_time(player);
}
CPS_play_all_media(player, (newtime == 0.0), newtime);
state = PLAYING;
[self stateHasChanged];
}
- (IBAction)stop:(id)sender
{
[time setDoubleValue:0];
needToSeek = YES;
if (CPS_get_session_state(player) == SESSION_DONE)
state = NOT_PLAYING;
if (state == PLAYING)
[self pause:sender];
else
[self stateHasChanged];
}
- (IBAction)close:(id)sender
{
SDL_Event event;
NSLog(@"Destroying player . . .");
event.type = SDL_QUIT;
SDL_PushEvent(&event);
CPS_destroy(player);
player = 0;
filename = nil;
state = CLOSED;
syncThreadStarted = NO;
[self stateHasChanged];
return;
}
- (IBAction)setVideoSize:(id)sender
{
BOOL setFullScreen = NO;
switch ([sender indexOfSelectedItem]) {
case 0: screenSize = 1; break;
case 1: case -1: screenSize = 2; break;
case 2: screenSize = 4; break;
case 3: setFullScreen = YES; break;
}
NSLog(@"set video size... %d", screenSize);
if (player)
CPS_set_screen_size(player, screenSize, setFullScreen);
/* if ((!player) && setFullScreen) do something useful */
}
- (IBAction)setLooping:(id)sender
{
if ([sender state] == NSOnState) {
NSRunAlertPanel(@"Error", @"Looping is not yet implemented", nil, nil, nil);
[sender setState:NSOffState];
}
return;
}
@end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -