This is SonyLDP1450.m in view mode; [Download] [Up]
/* SonyLDP1450.m 15 February 1993 Eric Celeste / AppTech / 5 Exeter Street / Belmont, MA 02178 efc@mit.edu Please send me any improvements. For example: player = [[SonyLDP1450 alloc] initDevice:"/dev/ttya" baud:B9600]; ... [player index:YES]; [player searchForFrame:400]; [player playForward]; sleep(40); [player still]; ... [player free]; See LDPlayer for a note about reporting errors to the outside world. I do not have Sony's documention for its LDP interface yet (the Interface Manual's part number is LDM-G1000, in case you care), so much of what follows could easily be wrong. I did my best based on my (possibly much flawed) reading of source code from David Small. In particular, I am not sure I have done the right thing with ack (maybe each command generates two ack characters, one when the command is received and one when the player is ready for the next command, see SonyLDPcodes.h for this hint), but it seems to work. I also think it should be possible to search for a CLV frame, but this object does not seem to make that possible. Maybe I should send a shorter (4 byte?) frame number when searching a CLV disk? Anyway, for the most part, this works. It is certainly in good enough shape to help others find their way around a laserdisc player. Enjoy! ...Eric ////////////////////////////////////////// History 930210 efc first adapted from David Small's Ultrix source code and used Michael Hawley's SerialPort object 930212 efc added chapter searching 930213 efc made this a subclass of generic LDPlayer 930214 efc added completion and fixed search & repeat 930215 efc switched to delegation method of error reporting */ #import "SonyLDP1450.h" #import "SonyLDPcodes.h" #define NOTHING 0x00 @implementation SonyLDP1450 ////////////////////////////////////////////// Private Functions const char *commandString(char cmd) { char tempStr[1000]; switch (cmd) { case NOTHING: return ("nothing"); case LDP_ACK: return ("Ack"); case LDP_NACK: return ("Nack"); case LDP_COMPLETION: return ("Completion"); case LDP_ERROR: return ("Error"); case LDP_LID_OPEN: return ("Lid Open"); case LDP_NO_FRAME: return ("No Frame"); case LDP_NOT_TARGET: return ("Not Target"); case LDP_CHAPTER_MODE: return ("Chapter Mode"); case LDP_CHAPTER_INQ: return ("Chapter Inq"); case LDP_ADDR_INQ: return ("Address Inq"); case LDP_FRAME_MODE: return ("Frame Mode"); case LDP_AUDIO_MUTE_OFF: return ("Mute Off"); case LDP_AUDIO_MUTE_ON: return ("Mute On"); case LDP_CH1_ON: return ("Channel 1 On"); case LDP_CH1_OFF: return ("Channel 1 Off"); case LDP_CH2_ON: return ("Channel 2 On"); case LDP_CH2_OFF: return ("Channel 2 Off"); case LDP_CX_ON: return ("Noise Reduction On"); case LDP_CX_OFF: return ("Noise Reduction Off"); case LDP_RESET: return ("Reset"); case LDP_EJECT: return ("Eject"); case LDP_EJECT_ENABLE: return ("Eject Enable"); case LDP_EJECT_DISABLE: return ("Eject Disable"); case LDP_SCAN_F: return ("Forw Scan"); case LDP_SCAN_R: return ("Rev Scan"); case LDP_FAST_F: return ("Forw Fast"); case LDP_FAST_R: return ("Rev Fast"); case LDP_PLAY_F: return ("Forw Play"); case LDP_PLAY_R: return ("Rev Play"); case LDP_SLOW_F: return ("Forw Slow"); case LDP_SLOW_R: return ("Rev Slow"); case LDP_ONE_FRAME_F: return ("Forw Frame"); case LDP_ONE_FRAME_R: return ("Rev Frame"); case LDP_INDEX_ON: return ("Index On"); case LDP_INDEX_OFF: return ("Index Off"); case LDP_MEMORY: return ("Memory Set"); case LDP_M_SEARCH: return ("Memory Search"); case LDP_MOTOR_ON: return ("Motor On"); case LDP_MOTOR_OFF: return ("Motor Off"); case LDP_STOP: return ("Stop"); case LDP_STILL: return ("Still"); case LDP_SEARCH: return ("Search"); case LDP_ENTER: return ("Enter"); case LDP_REPEAT: return ("Repeat"); case LDP_STATUS_INQ: return ("Status Inq"); default: sprintf (tempStr, "0x%.2x", (unsigned int)cmd); return (tempStr); } } ////////////////////////////////////////////// Private Methods - waitFor:(char)response { char c; char trouble[500]; c = [port getc]; if (c != response) { sprintf ( trouble, "%s expected %s, got %s", commandString(lastCommand), commandString(response), commandString(c) ); [self reportProblem:trouble]; } return self; } - command:(char) cmd { while ([port hasInput]) [self waitFor:NOTHING]; [port putc:cmd]; lastCommand = cmd; [self waitFor:LDP_ACK]; return self; } - frame:(int)frame { int i, digit; int div; allOK = YES; div = 10000; for (i = 0; i < 5; i++) { if (frame >= div) { digit = frame / div; frame = frame - (digit * div); } else { digit = 0; } div = div / 10; [self command:digit + 0x30]; } if(allOK) { [self command:LDP_ENTER]; } return self; } ////////////////////////////////////////////// Housekeeping Methods - initDevice:(const char *)device baud:(int)rate { self = [super initDevice:device baud:rate]; if (self) { lastCommand = '\0'; } return self; } ////////////////////////////////////////////// Control Methods - searchForChapter:(int)chapter { allOK = YES; [self command:LDP_CHAPTER_MODE]; if (allOK) { [self command:LDP_SEARCH]; if (allOK){ [self frame:chapter]; if (allOK){ [self waitFor:LDP_COMPLETION]; } } [self command:LDP_FRAME_MODE]; } return self; } - searchForFrame:(int)frame; { allOK = YES; [self command:LDP_SEARCH]; if (allOK) { [self frame:frame]; if (allOK) { [self waitFor:LDP_COMPLETION]; } } return self; } - still { return [self command:LDP_STILL]; } - halt { return [self command:LDP_STOP]; } - eject { return [self command:LDP_EJECT]; } - playForward { return [self command:LDP_PLAY_F]; } - playBack { return [self command:LDP_PLAY_R]; } - fastForward { return [self command:LDP_FAST_F]; } - fastBack { return [self command:LDP_FAST_R]; } - slowForward { return [self command:LDP_SLOW_F]; } - slowBack { return [self command:LDP_SLOW_R]; } - scanForward { return [self command:LDP_SCAN_F]; } - scanBack { return [self command:LDP_SCAN_R]; } - frameForward { return [self command:LDP_ONE_FRAME_F]; } - frameBack { return [self command:LDP_ONE_FRAME_R]; } - playFrom:(int)inFrame to:(int)outFrame repeating:(int)times; { char timecmd; allOK = YES; [self searchForFrame:inFrame]; if (allOK) { [self command:LDP_REPEAT]; if (allOK) { [self frame:outFrame]; if (allOK) { if (times > 9) times = 1; timecmd = 0x30 + times; [self command:timecmd]; if (allOK) { [self command:LDP_ENTER]; if (allOK) { [self waitFor:LDP_COMPLETION]; } } } } } return self; } - motor:(BOOL)on { allOK = YES; if (on) { [self command:LDP_MOTOR_ON]; if (allOK) { NXRunAlertPanel( [NXApp appName], "Please wait for the motor to spin up", "OK",NULL, NULL ); [self waitFor:LDP_ACK]; } } else { [self command:LDP_MOTOR_OFF]; if (allOK) { NXRunAlertPanel( [NXApp appName], "Please wait for the motor to spin down", "OK",NULL, NULL ); [self waitFor:LDP_ACK]; } } return self; } - index:(BOOL)on { if (on) { [self command:LDP_INDEX_ON]; } else { [self command:LDP_INDEX_OFF]; } return self; } - channelOne:(BOOL)on { if (on) { [self command:LDP_CH1_ON]; } else { [self command:LDP_CH1_OFF]; } return self; } - channelTwo:(BOOL)on { if (on) { [self command:LDP_CH2_ON]; } else { [self command:LDP_CH2_OFF]; } return self; } - mute:(BOOL)on { if (on) { [self command:LDP_AUDIO_MUTE_ON]; } else { [self command:LDP_AUDIO_MUTE_OFF]; } return self; } - noiseReduction:(BOOL)on { if (on) { [self command:LDP_CX_ON]; } else { [self command:LDP_CX_OFF]; } return self; } - clearAll { return [self command:LDP_RESET]; /* but we may still need to clear out a queue of waiting responses */ while ([port hasInput]) [self waitFor:NOTHING]; return self; } ////////////////////////////////////////////// Inquiry Methods - (int)currentFrame { int i; char str[10]; [port putc:LDP_ADDR_INQ]; for (i = 0; i < 5; i++) { str[i] = [port getc]; } str[i] = '\0'; return (atoi(str)); } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.