MODULE WMMixer;
IMPORT
Modules,
SoundDevices, Strings, Plugins, WMComponents, WMStandardComponents, WMMessages, WMWindowManager, WMProperties;
VAR
device : SoundDevices.Driver;
master : SoundDevices.MixerChannel;
StrMixer : Strings.String;
TYPE
String = Strings.String;
Mixer* = OBJECT(WMComponents.VisualComponent)
VAR
deviceName-, channelName- : WMProperties.StringProperty;
name : WMStandardComponents.Label;
value : WMStandardComponents.Scrollbar;
mute : WMStandardComponents.Checkbox;
channel : SoundDevices.MixerChannel;
device : SoundDevices.Driver;
PROCEDURE &Init*;
BEGIN
Init^;
NEW(deviceName, PrototypedeviceName, NIL, NIL); properties.Add(deviceName);
NEW(channelName, PrototypechannelName, NIL, NIL); properties.Add(channelName);
NEW(name); name.alignment.Set(WMComponents.AlignTop); name.bounds.SetHeight(20);
AddContent(name);
NEW(mute); mute.alignment.Set(WMComponents.AlignBottom); mute.bounds.SetHeight(20);
mute.caption.SetAOC("Mute");
mute.onClick.Add(MuteChanged);
AddContent(mute);
NEW(value); value.alignment.Set(WMComponents.AlignClient);
value.bearing.SetLeft(20); value.bearing.SetRight(20);
value.onPositionChanged.Add(VolChanged);
value.max.Set(255);
AddContent(value);
SetNameAsString(StrMixer);
END Init;
PROCEDURE MuteChanged(sender, data : ANY);
BEGIN
IF channel # NIL THEN
channel.SetMute(mute.state.Get () = WMStandardComponents.Checked);
END
END MuteChanged;
PROCEDURE RecacheProperties;
VAR s : String; dn, cn : ARRAY 128 OF CHAR;
BEGIN
RecacheProperties^;
s := deviceName.Get(); IF s # NIL THEN COPY(s^, dn) END;
s := channelName.Get(); IF s # NIL THEN COPY(s^, cn); name.caption.SetAOC(cn) END;
IF device # NIL THEN device.UnregisterMixerChangeListener(MixerChangeListener) END;
FindChannel(dn, cn, device, channel);
IF channel # NIL THEN
sequencer.ScheduleEvent(SELF.MixerChangeEvent, device, channel)
END;
IF device # NIL THEN device.RegisterMixerChangeListener(MixerChangeListener) END;
END RecacheProperties;
PROCEDURE MixerChangeListener(channel : SoundDevices.MixerChannel);
BEGIN
sequencer.ScheduleEvent(SELF.MixerChangeEvent, device, channel)
END MixerChangeListener;
PROCEDURE MixerChangeEvent(sender, data : ANY);
VAR vol : LONGINT; m : BOOLEAN;
BEGIN
IF (data = channel) & (channel # NIL) THEN
vol := channel.GetVolume();
m := channel.GetIsMute();
value.pos.Set(255 - vol);
IF m THEN mute.state.Set(WMStandardComponents.Checked)
ELSE mute.state.Set(WMStandardComponents.Unchecked)
END;
END;
END MixerChangeEvent;
PROCEDURE VolChanged(sender, data : ANY);
BEGIN
IF channel # NIL THEN
channel.SetVolume(255 - value.pos.Get())
END
END VolChanged;
PROCEDURE FindChannel(deviceName, channelName : ARRAY OF CHAR; VAR dev : SoundDevices.Driver; VAR channel : SoundDevices.MixerChannel);
VAR i : LONGINT; ch : SoundDevices.MixerChannel; name : ARRAY 128 OF CHAR;
p : Plugins.Plugin;
BEGIN
p := SoundDevices.devices.Get(deviceName);
channel := NIL;
IF (p # NIL) & (p IS SoundDevices.Driver) THEN dev := p(SoundDevices.Driver) ELSE dev := NIL END;
IF dev # NIL THEN
FOR i := 0 TO dev.GetNofMixerChannels() - 1 DO
dev.GetMixerChannel(i, ch);
ch.GetName(name);
IF name = channelName THEN channel := ch END;
END;
END
END FindChannel;
PROCEDURE Finalize;
BEGIN
Finalize^;
IF device # NIL THEN device.UnregisterMixerChangeListener(MixerChangeListener) END;
END Finalize;
END Mixer;
KillerMsg = OBJECT
END KillerMsg;
Window* = OBJECT (WMComponents.FormWindow)
PROCEDURE &New*;
VAR vc : WMComponents.VisualComponent;
BEGIN
IncCount;
vc := CreateForm();
Init(vc.bounds.GetWidth(), vc.bounds.GetHeight(), FALSE);
SetContent(vc);
WMWindowManager.DefaultAddWindow(SELF);
SetTitle(Strings.NewString("Mixer"));
END New;
PROCEDURE CreateForm(): WMComponents.VisualComponent;
VAR panel : WMStandardComponents.Panel;
dev : SoundDevices.Driver;
i : LONGINT;
ch : SoundDevices.MixerChannel;
name : ARRAY 128 OF CHAR;
m : Mixer;
CONST MWidth = 60;
BEGIN
dev := SoundDevices.GetDefaultDevice();
NEW(panel); panel.bounds.SetExtents(MWidth * dev.GetNofMixerChannels(), 200); panel.fillColor.Set(LONGINT(0FFFFFFFFH)); panel.takesFocus.Set(TRUE);
IF dev # NIL THEN
FOR i := 0 TO dev.GetNofMixerChannels() - 1 DO
dev.GetMixerChannel(i, ch);
ch.GetName(name);
NEW(m);
m.alignment.Set(WMComponents.AlignLeft); m.bounds.SetWidth(MWidth);
m.channelName.SetAOC(name);
panel.AddContent(m);
END;
END;
RETURN panel
END CreateForm;
PROCEDURE Close;
BEGIN
DecCount;
Close^;
END Close;
PROCEDURE Handle(VAR x: WMMessages.Message);
BEGIN
IF (x.msgType = WMMessages.MsgExt) & (x.ext # NIL) & (x.ext IS KillerMsg) THEN Close
ELSE Handle^(x)
END
END Handle;
END Window;
VAR
PrototypedeviceName, PrototypechannelName: WMProperties.StringProperty;
nofWindows : LONGINT;
PROCEDURE Open*;
VAR inst : Window;
BEGIN
NEW(inst);
END Open;
PROCEDURE IncCount;
BEGIN {EXCLUSIVE}
INC(nofWindows);
END IncCount;
PROCEDURE DecCount;
BEGIN {EXCLUSIVE}
DEC(nofWindows);
END DecCount;
PROCEDURE MasterIncVol*;
BEGIN
IF master = NIL THEN
device := SoundDevices.GetDefaultDevice();
device.GetMixerChannel(0, master)
END;
IF master # NIL THEN
master.SetVolume(Strings.Min(255, master.GetVolume() + 4))
END;
END MasterIncVol;
PROCEDURE MasterDecVol*;
BEGIN
IF master = NIL THEN
device := SoundDevices.GetDefaultDevice();
device.GetMixerChannel(0, master)
END;
IF master # NIL THEN
master.SetVolume(Strings.Max(0, master.GetVolume() - 4))
END;
END MasterDecVol;
PROCEDURE Cleanup;
VAR die : KillerMsg;
msg : WMMessages.Message;
m : WMWindowManager.WindowManager;
BEGIN {EXCLUSIVE}
NEW(die); msg.ext := die; msg.msgType := WMMessages.MsgExt;
m := WMWindowManager.GetDefaultManager();
m.Broadcast(msg);
AWAIT(nofWindows = 0)
END Cleanup;
BEGIN
Modules.InstallTermHandler(Cleanup);
NEW(PrototypedeviceName, NIL, Strings.NewString(""), Strings.NewString("Name of the associated sound device"));
NEW(PrototypechannelName, NIL, Strings.NewString("MasterVol"), Strings.NewString("Name of the associated sound channel"));
StrMixer := Strings.NewString("Mixer");
END WMMixer.
WMMixer.Open ~
SystemTools.Free WMMixer ~
WMMixer.MasterDecVol ~