MODULE TVDriver;
IMPORT
SYSTEM, Plugins, Modules, KernelLog, Strings, ActiveTimers;
CONST
RegistryName = "TVDriver";
RegistryDesc = "TV drivers for Bluebottle";
WesternEuropeanChnlSet* = 0;
VbiMaxLines* = 16;
VbiLineSize* = 2048;
VbiBufferItems = 20;
VbiDataSize* = VbiLineSize * VbiMaxLines * 2;
VbiBufferSize* = VbiDataSize * VbiBufferItems;
TYPE
VbiBuffer* = OBJECT
VAR
data*: ARRAY VbiBufferSize OF CHAR;
readPos*: LONGINT;
insertPos*: LONGINT;
vbiSize*: LONGINT;
timeout: BOOLEAN;
timer: ActiveTimers.Timer;
PROCEDURE &Init*;
BEGIN
NEW(timer);
timeout := FALSE;
END Init;
PROCEDURE TimeoutHandler;
BEGIN {EXCLUSIVE}
timeout := TRUE
END TimeoutHandler;
PROCEDURE AwaitData*;
BEGIN {EXCLUSIVE}
timer.SetTimeout(TimeoutHandler, 200);
timeout := FALSE;
AWAIT ((vbiSize > 0) OR timeout);
timer.CancelTimeout;
END AwaitData;
PROCEDURE Finalize*;
BEGIN {EXCLUSIVE}
timeout := TRUE;
timer.Finalize;
END Finalize;
END VbiBuffer;
TVTuner* = OBJECT
VAR
frequency*: LONGINT;
PROCEDURE & Init* (vcd: VideoCaptureDevice);
BEGIN HALT(99)
END Init;
PROCEDURE OpenVbi* (): LONGINT;
BEGIN HALT(99)
END OpenVbi;
PROCEDURE CloseVbi*;
BEGIN HALT(99)
END CloseVbi;
PROCEDURE Open*;
BEGIN HALT(99)
END Open;
PROCEDURE Close*;
BEGIN HALT(99)
END Close;
PROCEDURE SetChannelSet* (chnlSet: LONGINT);
BEGIN HALT(99)
END SetChannelSet;
PROCEDURE GetChannelSet* (): LONGINT;
BEGIN HALT(99)
END GetChannelSet;
PROCEDURE SetChannel* (chnl: LONGINT);
BEGIN HALT(99)
END SetChannel;
PROCEDURE GetChannel* (): LONGINT;
BEGIN HALT(99);
END GetChannel;
PROCEDURE GetMaxChannel* (): LONGINT;
BEGIN HALT(99);
END GetMaxChannel;
PROCEDURE SetTVFrequency* (freq: LONGINT);
BEGIN
NotifyChannelSwitchObservers (freq);
SetTVFrequencyImpl (freq);
END SetTVFrequency;
PROCEDURE SetTVFrequencyImpl* (freq: LONGINT);
BEGIN
HALT(99);
END SetTVFrequencyImpl;
PROCEDURE GetFrequency* (): LONGINT;
BEGIN
RETURN frequency
END GetFrequency;
PROCEDURE SetRadioFrequency* (freq: LONGINT);
BEGIN HALT(99);
END SetRadioFrequency;
PROCEDURE InstallChannelSwitchHandler* (handler: ChannelSwitchHandler);
VAR
chObs: ChannelSwitchObserver;
BEGIN
NEW (chObs);
chObs.handler := handler;
chObs.next := channelSwitchObservers;
channelSwitchObservers := chObs;
END InstallChannelSwitchHandler;
PROCEDURE NotifyChannelSwitchObservers (freq: LONGINT);
VAR
chObs: ChannelSwitchObserver;
BEGIN
chObs := channelSwitchObservers;
WHILE chObs # NIL DO
chObs.handler (freq, SELF);
chObs := chObs.next;
END;
END NotifyChannelSwitchObservers;
PROCEDURE GetTunerStatus* (): LONGINT;
BEGIN HALT(99);
END GetTunerStatus;
PROCEDURE CalcFieldStrength* (): LONGINT;
BEGIN HALT(99);
END CalcFieldStrength;
PROCEDURE IsLocked* (): BOOLEAN;
BEGIN HALT(99);
END IsLocked;
PROCEDURE IsStereo* (): BOOLEAN;
BEGIN HALT(99);
END IsStereo;
PROCEDURE SetHue* (hue: LONGINT);
BEGIN HALT(99);
END SetHue;
PROCEDURE GetHue* (): LONGINT;
BEGIN HALT(99);
END GetHue;
PROCEDURE SetBrightness* (brightness: LONGINT);
BEGIN HALT(99);
END SetBrightness;
PROCEDURE GetBrightness* (): LONGINT;
BEGIN HALT(99);
END GetBrightness;
PROCEDURE SetChromaSaturation* (saturation: LONGINT);
BEGIN HALT(99);
END SetChromaSaturation;
PROCEDURE GetChromaSaturation* (): LONGINT;
BEGIN HALT(99);
END GetChromaSaturation;
PROCEDURE SetChromaVSaturation* (saturation: LONGINT);
BEGIN HALT(99);
END SetChromaVSaturation;
PROCEDURE GetChromaVSaturation* (): LONGINT;
BEGIN HALT(99);
END GetChromaVSaturation;
PROCEDURE SetChromaUSaturation* (saturation: LONGINT);
BEGIN HALT(99);
END SetChromaUSaturation;
PROCEDURE GetChromaUSaturation* (): LONGINT;
BEGIN HALT(99);
END GetChromaUSaturation;
PROCEDURE SetLumaNotch* (notch: LONGINT);
BEGIN HALT(99);
END SetLumaNotch;
PROCEDURE GetLumaNotch* (): LONGINT;
BEGIN HALT(99);
END GetLumaNotch;
PROCEDURE SetContrast* (contrast: LONGINT);
BEGIN HALT(99);
END SetContrast;
PROCEDURE GetContrast* (): LONGINT;
BEGIN HALT(99);
END GetContrast;
PROCEDURE SetColorBars* (enable: BOOLEAN);
BEGIN HALT(99);
END SetColorBars;
END TVTuner;
ChannelSwitchHandler* = PROCEDURE {DELEGATE} (freq: LONGINT; tuner: TVTuner);
ChannelSwitchObserver = OBJECT
VAR
next: ChannelSwitchObserver;
handler: ChannelSwitchHandler;
END ChannelSwitchObserver;
NotificationHandler* = PROCEDURE {DELEGATE};
VideoCaptureDevice* = OBJECT (Plugins.Plugin)
PROCEDURE & Init* (base: SYSTEM.ADDRESS; irq, product, rev: LONGINT);
BEGIN HALT(99);
END Init;
PROCEDURE GetVbiBuffer* (): VbiBuffer;
BEGIN HALT(99);
END GetVbiBuffer;
PROCEDURE GetTuner* (): TVTuner;
BEGIN HALT(99);
END GetTuner;
PROCEDURE GetAudio* (): Audio;
BEGIN HALT(99);
END GetAudio;
PROCEDURE InstallNotificationHandler* (handler: NotificationHandler);
BEGIN HALT(99);
END InstallNotificationHandler;
PROCEDURE VideoOpen*;
BEGIN HALT(99);
END VideoOpen;
PROCEDURE VideoClose*;
BEGIN HALT(99);
END VideoClose;
PROCEDURE IsVideoOpen* (): BOOLEAN;
BEGIN HALT(99);
END IsVideoOpen;
PROCEDURE IsVbiOpen* (): BOOLEAN;
BEGIN HALT(99);
END IsVbiOpen;
PROCEDURE SetClipRegion*;
BEGIN HALT(99);
END SetClipRegion;
PROCEDURE GetStatus* (): LONGINT;
BEGIN HALT(99);
END GetStatus;
PROCEDURE SetInputFormat* (format: LONGINT);
BEGIN HALT(99);
END SetInputFormat;
PROCEDURE GetInputFormat* (): LONGINT;
BEGIN HALT(99);
END GetInputFormat;
PROCEDURE SetPixelFormat* (format: LONGINT);
BEGIN HALT(99);
END SetPixelFormat;
PROCEDURE SetInputDev0*;
BEGIN HALT(99);
END SetInputDev0;
PROCEDURE SetInputDev1*;
BEGIN HALT(99);
END SetInputDev1;
PROCEDURE SetInputDev2*;
BEGIN HALT(99);
END SetInputDev2;
PROCEDURE SetInputDevSVideo*;
BEGIN HALT(99);
END SetInputDevSVideo;
PROCEDURE SetInputDev3*;
BEGIN HALT(99);
END SetInputDev3;
PROCEDURE SetVideo* (addr: SYSTEM.ADDRESS; width: LONGINT);
BEGIN HALT(99);
END SetVideo;
PROCEDURE CaptureSingle*;
BEGIN HALT(99);
END CaptureSingle;
PROCEDURE CaptureContinuous*;
BEGIN HALT(99);
END CaptureContinuous;
PROCEDURE StopCaptureContinuous*;
BEGIN HALT(99);
END StopCaptureContinuous;
PROCEDURE SetGeometry* (columns, rows, frames: LONGINT; format: SET);
BEGIN HALT(99);
END SetGeometry;
END VideoCaptureDevice;
Audio* = OBJECT
PROCEDURE & Init* (vcd: VideoCaptureDevice);
BEGIN HALT(99);
END Init;
PROCEDURE SetAudioTuner*;
BEGIN HALT(99);
END SetAudioTuner;
PROCEDURE SetAudioExtern*;
BEGIN HALT(99);
END SetAudioExtern;
PROCEDURE SetAudioIntern*;
BEGIN HALT(99);
END SetAudioIntern;
PROCEDURE SetAudioMute*;
BEGIN HALT(99);
END SetAudioMute;
PROCEDURE SetAudioUnmute*;
BEGIN HALT(99);
END SetAudioUnmute;
PROCEDURE IsAudioMute* (): BOOLEAN;
BEGIN HALT(99);
END IsAudioMute;
END Audio;
VAR
channelSwitchObservers: ChannelSwitchObserver;
devices*:Plugins.Registry;
PROCEDURE GetVideoDevice* (idx: LONGINT): VideoCaptureDevice;
VAR
devName : ARRAY 32 OF CHAR;
nr: ARRAY 4 OF CHAR;
dev: Plugins.Plugin;
BEGIN
devName := RegistryName;
Strings.IntToStr(idx, nr);
Strings.Append(devName, nr);
dev := devices.Get(devName);
IF dev # NIL THEN
RETURN dev(VideoCaptureDevice)
ELSE
RETURN NIL
END
END GetVideoDevice;
PROCEDURE GetDefaultDevice*() : VideoCaptureDevice;
VAR p : Plugins.Plugin;
BEGIN
p := devices.Get ("");
IF p = NIL THEN
KernelLog.String ("{TVDriver} Error: No video capture device detected.");
KernelLog.Ln;
RETURN NIL
END;
ASSERT (p IS VideoCaptureDevice);
RETURN p(VideoCaptureDevice);
END GetDefaultDevice;
PROCEDURE Cleanup;
BEGIN
Plugins.main.Remove (devices)
END Cleanup;
BEGIN
NEW(devices, RegistryName, RegistryDesc);
Modules.InstallTermHandler (Cleanup);
END TVDriver.
Note: The TV Application gets non-default devices via the GetVideoDevice() routine.
All VideoCaptureDevices which are added to the devices registry must have the empty string as name!
Example:
MODULE MyTVDriver;
PROCEDURE Install*;
VAR
dev: TVDriver.VideoCaptureDevice;
res: LONGINT;
BEGIN
NEW(dev);
... set the device properties ...
dev.SetName("");
TVDriver.devices.Add(dev, res);
ASSERT (res = Plugins.Ok)
END Install;