This is MPEGThread.m in view mode; [Download] [Up]
// MPEGThread.m
#import <mach/mach.h> // post_allocate()
#import <mach/mach_error.h>
#import <dpsclient/dpsNeXT.h> // DPSAddPort()
#import <objc/NXBundle.h>
#import <appkit/Application.h>
#import <appkit/Panel.h>
// local objects
#import "MPEGView.h"
#import "MPEGThread.h"
#define SEND_FCODE(x) \
pkt.fcode = x; \
mr = msg_send((msg_header_t *)&pkt, MSG_OPTION_NONE, 0); \
if (SEND_SUCCESS != mr) \
fprintf(stderr, "msg_send() failed with error %d\n", mr);
@implementation MPEGThread
/*** Initialization methods ***/
- initSize:(int)size forView:anObject
{
kern_return_t kr;
if (![super init])
return nil;
frameSize = size;
view = anObject;
controller = [NXApp delegate];
if (KERN_SUCCESS != (kr = port_allocate(task_self(), &mpegPort)))
{
mach_error("port_allocate() failed in -initSize:forView:", kr);
return [self free];
}
DPSAddPort(mpegPort, (DPSPortProc)receive_fcode, sizeof(mpegPacket),
(void *)self, NX_MODALRESPTHRESHOLD + 1);
return self;
}
- free
{
kern_return_t kr;
[self abortDecode];
DPSRemovePort(mpegPort);
if (KERN_SUCCESS != (kr = port_deallocate(task_self(), mpegPort)))
mach_error("port_deallocate() failed in -free", kr);
return [super free];
}
/*** Instance methods and Standard C wrapper functions ***/
void receive_fcode(mpegPacket *pkt, id self)
{
[self receiveFcode:pkt];
}
- receiveFcode:(mpegPacket *)pkt
{
switch (pkt->fcode)
{
case FCODE_ABORT:
[self abortDecode];
break;
case FCODE_END:
[view setAddress:(char *)address len:(int)len maxlen:(int)maxlen];
[view runAgain];
[self endDecode];
break;
default:
if ([controller respondsTo:@selector(setFrameNumber:)])
[controller setFrameNumber:pkt->fcode];
break;
}
return self;
}
- decodeFile:(const char *)mpegFile
{
char *pchAlertTitle = "Error in MPEGThread method -decodeFile:";
char command[256];
// check for NULL pointer or empty string
if (!mpegFile || !*mpegFile)
{
NXRunAlertPanel(pchAlertTitle, "No filename was specified.",
gpchOK, NULL, NULL);
return nil;
}
sprintf(command, "exec %s/mpegDecode %s",
[[NXBundle mainBundle] directory], mpegFile);
if (NULL == (ifp = popen(command, "r")))
{
NXRunAlertPanel(pchAlertTitle,
"Could not create MPEG Decode process. Command:%s",
gpchOK, NULL, NULL, command);
return nil;
}
if (NULL == (buffer = malloc(frameSize)))
{
NXRunAlertPanel(pchAlertTitle, "Could not allocate memory.",
gpchOK, NULL, NULL);
pclose(ifp);
return nil;
}
// REVIEW: check the following for errors returned?
pStream = NXOpenFile(fileno(ifp), O_RDONLY);
mStream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
[controller setFrameNumber:0];
cthreadMain = cthread_fork(mpeg_thread, self);
cthread_detach(cthreadMain);
return self;
}
any_t mpeg_thread(any_t self)
{
[(MPEGThread *)self mpegThread];
return self;
}
- mpegThread
{
mpegPacket pkt;
int frameNumber;
msg_return_t mr;
pkt.h.msg_remote_port = mpegPort;
pkt.h.msg_simple = TRUE;
pkt.h.msg_size = sizeof(mpegPacket);
pkt.h.msg_local_port = PORT_NULL;
pkt.h.msg_type = MSG_TYPE_NORMAL;
pkt.t.msg_type_name = MSG_TYPE_INTEGER_32;
pkt.t.msg_type_size = 32;
pkt.t.msg_type_number = FP_NUM_INT_DATA;
pkt.t.msg_type_inline = TRUE;
pkt.t.msg_type_longform = FALSE;
pkt.t.msg_type_deallocate = FALSE;
for (frameNumber = 1; 1; frameNumber++)
{
int bytes = frameSize;
if (!(bytes = NXRead(pStream, buffer, bytes)))
break;
if (NXWrite(mStream, buffer, bytes) != bytes)
{
SEND_FCODE(FCODE_ABORT);
fprintf(stderr, "NXWrite() failed in -mpegThread\n");
return nil;
}
SEND_FCODE(frameNumber);
}
NXFlush(mStream);
NXGetMemoryBuffer(mStream, &address, &len, &maxlen);
NXCloseMemory(mStream, NX_SAVEBUFFER);
mStream = NULL;
SEND_FCODE(FCODE_END);
return self;
}
- endDecode
{
kern_return_t kr;
id result = self;
if (cthreadMain)
{
if (KERN_SUCCESS != (kr = thread_suspend(cthread_thread(cthreadMain))))
{
result = nil; // error suspending thread
mach_error("thread_suspend() failed in -endDecode", kr);
}
if (KERN_SUCCESS != (kr = cthread_abort(cthreadMain)))
{
result = nil; // error aborting thread
mach_error("cthread_abort() failed in -endDecode", kr);
}
else cthreadMain = 0;
}
if (buffer)
free(buffer);
buffer = NULL;
if (pStream)
NXClose(pStream);
pStream = NULL;
if (ifp)
pclose(ifp);
ifp = NULL;
return result;
}
- abortDecode
{
[self endDecode];
if (mStream)
NXCloseMemory(mStream, NX_FREEBUFFER);
address = NULL, len = maxlen = 0;
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.