Recent

Author Topic: The bells. the bells...  (Read 1126 times)

MarkMLl

  • Sr. Member
  • ****
  • Posts: 285
The bells. the bells...
« on: November 15, 2019, 09:37:08 pm »
Is there a fairly portable way of getting a beep out of an LCL program, typically not invoked from the system console or an SSH shell?

I'm porting a program originally written using Delphi which happily goes "beep" when I output #$07.

So far the only way I can get a beep in e.g. a Linux ssh session is to run the xkbbell utility.

I could obviously start messing around with Alsa etc., but is there a "correct" way of doing this?

It's nothing of earth-shattering importance, merely a simulated getty to test a simulated modem.

As usual, apologies if this is a frequently-answered question.

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.

sstvmaster

  • Full Member
  • ***
  • Posts: 131
Re: The bells. the bells...
« Reply #1 on: November 15, 2019, 09:51:34 pm »
Hi,

Beep is in unit SysUtils eg:
Code: Pascal  [Select]
  1. SysUtils.Beep;

and in unit Windows:
Code: Pascal  [Select]
  1. Windows.Beep(1000,250);
Lazarus 2.0.4 x32
Lazarus 2.1.0 Trunk x32
OS Win 7 32bit

MarkMLl

  • Sr. Member
  • ****
  • Posts: 285
Re: The bells. the bells...
« Reply #2 on: November 15, 2019, 10:05:21 pm »
Sysutils.Beep has no apparent effect inside an LCL-based app (not started from a shell session etc.). I presume the Windows unit is Windows-specific.

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.

MarkMLl

  • Sr. Member
  • ****
  • Posts: 285
Re: The bells. the bells...
« Reply #3 on: November 17, 2019, 12:39:07 pm »
Emphasising that this is an X11-specific question, I've been having a bit of a play with this referring to the source of xkbbell (in C) and the relevant FPC libraries.

https://gitlab.freedesktop.org/xorg/app/xkbutils/blob/master/xkbbell.c

Cutting out all the optional parameters I'm left with

Code: Pascal  [Select]
  1. program xkbbell;
  2.  
  3. uses
  4.   xkb, xkblib, xlib, x;
  5.  
  6. var
  7.   dpyName: string= '';
  8.   volume: integer= 99;
  9.   devSpec: integer= xkb.XkbUseCoreKbd;
  10.   xlass: integer= -1;
  11.   id: integer= -1;
  12.   bellName: string= '';
  13.   nameAtom: TAtom= x.None;
  14.   synch: integer= 0;
  15.   win: integer= x.None;
  16.   force: integer= 0;
  17.   nobeep: integer= 0;
  18.  
  19.  
  20. function parseArgs(): integer;
  21.  
  22. begin
  23.   result := 1
  24. end { parseArgs } ;
  25.  
  26.  
  27. var
  28.   dpy: PDisplay;
  29.   ok: boolean;
  30.  
  31.  
  32. begin
  33.   if parseArgs() < 1 then begin
  34.     WriteLn(StdErr, 'Sorry, helpless');
  35.     Halt(1)
  36.   end;
  37.   dpy := XOpenDisplay(nil (* PChar(dpyName) *) );
  38.   if dpy = nil then begin
  39.     WriteLn(StdErr, 'Couldn''t open display ""');
  40.     Halt(1)
  41.   end;
  42. //  ok := xkblib.XkbForceBell(dpy, volume);
  43.   ok := xkblib.XkbBell(dpy, win, volume, nameAtom);
  44.   if not ok then
  45.     WriteLn(StdErr, 'XkbBell request failed')
  46. end.
  47.  

The program compiles without error and runs without complaint, but is silent. xkbbell as shipped by Debian beeps as expected.

I might try to put a bit more time into it later in case one of the library calls checking extension etc. is actually enabling the extension, but apart from that does anybody have any thoughts or suggestions?

MarkMLl

Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.

Thaddy

  • Hero Member
  • *****
  • Posts: 9285
Re: The bells. the bells...
« Reply #4 on: November 17, 2019, 02:54:33 pm »
The bell signal is a real problem if there is no old school speaker available.
Try this to test:
Code: Pascal  [Select]
  1. var
  2.   T:Text;
  3. begin
  4.   Assign(T,'/dev/tty');
  5.   Rewrite(T);
  6.   Writeln(T,#7);
  7.   Flush(T);
  8.   Close(T);
  9. end.
If that produces no sound, the pcspkr kernel module is either not loaded or there is no supported speaker.
The above code is similar to
Code: Bash  [Select]
  1. # produces a sound if there is support for it
  2. echo -ne '\007'
Code: Bash  [Select]
  1. # test speaker support
  2. sudo modprobe pcspkr
If neither of these produce a sound, your hardware does not have support for it even if a speaker is present.

As an alternative I often use a short wav file and use the alsa system to reproduce the sound.

« Last Edit: November 17, 2019, 03:06:10 pm by Thaddy »
also related to equus asinus.

winni

  • Hero Member
  • *****
  • Posts: 590
Re: The bells. the bells...
« Reply #5 on: November 17, 2019, 03:40:55 pm »
Hi!

In the most new PCs there is no PC speaker - they saved one € - or less.

As mplayer is installed by default in all distros I know just do

Code: Bash  [Select]
  1. mplayer MyFunny.wav

as your personal alarm sound

Winni


MarkMLl

  • Sr. Member
  • ****
  • Posts: 285
Re: The bells. the bells...
« Reply #6 on: November 17, 2019, 03:51:59 pm »
[Sigh] On a fairly standard Linux desktop

0 1>markMLl@desktop:~$ echo -ne '\007'

does nothing.

0 1>markMLl@desktop:~$ xkbbell

Beeps.

Look, guys, I thought I'd already said

> xkbbell as shipped by Debian beeps as expected.

That uses the X11 extensions, and looking at various systems around here has been shipped as standard since at least 2000.

Now in principle it should be possible to transcribe xkbbell.c into Pascal. So far I've not got that working, and suspect that it's one of the version-check calls I omitted.

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.

winni

  • Hero Member
  • *****
  • Posts: 590
Re: The bells. the bells...
« Reply #7 on: November 17, 2019, 04:22:18 pm »
Hi!

Yes : xkbbell is shipped with suse distros but it did not work in 9.xx and now it does not work with Tumbleweed. That's why I am using mplayer.

Winni

zeljko

  • Hero Member
  • *****
  • Posts: 1089
    • http://wiki.lazarus.freepascal.org/User:Zeljan
Re: The bells. the bells...
« Reply #8 on: November 17, 2019, 05:04:22 pm »
Code: Pascal  [Select]
  1. program xkbbell;
  2.  
  3. uses
  4.   xkb, xkblib, xlib, x;
  5.  
  6. var
  7.   dpyName: string= '';
  8.   volume: integer= 99;
  9.   devSpec: integer= xkb.XkbUseCoreKbd;
  10.   xlass: integer= -1;
  11.   id: integer= -1;
  12.   bellName: string= '';
  13.   nameAtom: TAtom= x.None;
  14.   synch: integer= 0;
  15.   win: integer= x.None;
  16.   force: integer= 0;
  17.   nobeep: integer= 0;
  18.  
  19.  
  20. function parseArgs(): integer;
  21.  
  22. begin
  23.   result := 1
  24. end { parseArgs } ;
  25.  
  26.  
  27. var
  28.   dpy: PDisplay;
  29.   ok: boolean;
  30.  
  31.  
  32. begin
  33.   if parseArgs() < 1 then begin
  34.     WriteLn(StdErr, 'Sorry, helpless');
  35.     Halt(1)
  36.   end;
  37.   dpy := XOpenDisplay(nil (* PChar(dpyName) *) );
  38.   if dpy = nil then begin
  39.     WriteLn(StdErr, 'Couldn''t open display ""');
  40.     Halt(1)
  41.   end;
  42. //  ok := xkblib.XkbForceBell(dpy, volume);
  43.   ok := xkblib.XkbBell(dpy, win, volume, nameAtom);
  44.   if not ok then
  45.     WriteLn(StdErr, 'XkbBell request failed')
  46. end.
  47.  

1.win param should not be integer
2.try to call xkbBell with rootWindow as win param

MarkMLl

  • Sr. Member
  • ****
  • Posts: 285
Re: The bells. the bells...
« Reply #9 on: November 17, 2019, 06:24:47 pm »
Yes : xkbbell is shipped with suse distros but it did not work in 9.xx and now it does not work with Tumbleweed. That's why I am using mplayer.

Is that another casualty of attempts to migrate towards Wayland?

mplayer is a bit OTT for a single beep. Other members of the program suite (still running on Windows) use MIDI for simple annunciator "jingles" and I'll probably use ALSA to replicate that, but again it's overkill for a simple beep.

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.

MarkMLl

  • Sr. Member
  • ****
  • Posts: 285
Re: The bells. the bells...
« Reply #10 on: November 17, 2019, 09:16:29 pm »
1.win param should not be integer
2.try to call xkbBell with rootWindow as win param

1: Muy bad, I plead that was due to its being a transcript from C. In actual fact it didn't apply if I used xkblib.XkbForceBell().

2: If I use  ok := xkblib.XkbBell(dpy, rootWindow(dpy, DefaultScreen(dpy)), 99, nameAtom);  it's still silent.

I used the usage of RootWindow() in TGtkWidgetSet.GetCursorPos()

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.

MarkMLl

  • Sr. Member
  • ****
  • Posts: 285
Re: The bells. the bells...
« Reply #11 on: November 17, 2019, 09:40:10 pm »
I've added a couple more version etc. calls with no obvious improvement. Code now looks like

Code: Pascal  [Select]
  1. program xkbbell;
  2.  
  3. uses
  4.   xkb, xkblib, xlib, x;
  5.  
  6. var
  7.   dpyName: string= '';
  8.   volume: integer= 99;
  9.   devSpec: integer= xkb.XkbUseCoreKbd;
  10.   xlass: integer= -1;
  11.   id: integer= -1;
  12.   bellName: string= '';
  13.   nameAtom: TAtom= x.None;
  14.   synch: integer= 0;
  15.   win: TWindow= x.None;
  16.   force: integer= 0;
  17.   nobeep: integer= 0;
  18.  
  19.  
  20. function parseArgs(): integer;
  21.  
  22. begin
  23.   result := 1
  24. end { parseArgs } ;
  25.  
  26.  
  27. const
  28.   XkbMajorVersion= 1;
  29.   XkbMinorVersion= 0;
  30.  
  31. var
  32.   dpy: PDisplay;
  33.   ok: boolean;
  34.   i1: smallint= XkbMajorVersion;
  35.   i2: smallint= XkbMinorVersion;
  36.   i3, i4, i5: smallint;
  37.  
  38.  
  39. begin
  40.   if parseArgs() < 1 then begin
  41.     WriteLn(StdErr, 'Sorry, helpless');
  42.     Halt(1)
  43.   end;
  44.   dpy := XOpenDisplay(nil (* PChar(dpyName) *) );
  45.   if dpy = nil then begin
  46.     WriteLn(StdErr, 'Couldn''t open display ""');
  47.     Halt(1)
  48.   end;
  49.   if not XkbLibraryVersion(@i1, @i2) then begin
  50.     WriteLn(StdErr, 'Wrong xkblib library version');
  51.     Halt(1)
  52.   end;
  53.   if not XkbQueryExtension(dpy, @i1, @i2, @i3, @i4, @i5) then begin
  54.     WriteLn(StdErr, 'Wrong xkblib extension');
  55.     Halt(1)
  56.   end;
  57.  
  58.   ok := xkblib.XkbForceBell(dpy, volume);
  59. //  ok := xkblib.XkbBell(dpy, win, volume, nameAtom);
  60. //  ok := xkblib.XkbBell(dpy, rootWindow(dpy, DefaultScreen(dpy)), 99, nameAtom);
  61.  
  62.   if not ok then
  63.     WriteLn(StdErr, 'XkbBell request failed')
  64. end.
  65.  

If nobody's got any last-minute suggestions I'll probably simply invoke the distro-provided xkbbell binary. I know that works, I've just been looking and can see no unexpected setuid or capabilities setting.

MarkMLl
« Last Edit: November 17, 2019, 09:50:18 pm by MarkMLl »
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.

PascalDragon

  • Hero Member
  • *****
  • Posts: 716
  • Compiler Developer
Re: The bells. the bells...
« Reply #12 on: November 18, 2019, 09:16:55 am »
In the most new PCs there is no PC speaker - they saved one € - or less.
Usually at least the OS routes it through the soundcard then (e.g. on my Windows the Bell signal of the Windows Services for Linux shell always comes through the soundcard and even my nearly 15 year old laptop (which did not have any PC speaker either) routes the BIOS beeps through the soundcard).

As mplayer is installed by default in all distros I know just do
That's a very bold statement. Neither Debian, nor ArchLinux, nor Gentoo install it by default.[/quote]

MarkMLl

  • Sr. Member
  • ****
  • Posts: 285
Re: The bells. the bells...
« Reply #13 on: November 23, 2019, 12:43:08 pm »
Stepping through the C original with gdb indicates that since synchronous operation isn't being forced, the beep isn't output until the display is closed. The code below is adequate:
Code: Pascal  [Select]
  1. program xkbbell;
  2.  
  3. uses
  4.   xkblib, xlib;
  5.  
  6. var
  7.   dpy: PDisplay;
  8.   ok: boolean;
  9.  
  10. begin
  11.   dpy := XOpenDisplay(nil);
  12.   if dpy = nil then begin
  13.     WriteLn(StdErr, 'Couldn''t open display ""');
  14.     Halt(1)
  15.   end;
  16.   ok := xkblib.XkbForceBell(dpy, 100);
  17.   if not ok then
  18.     WriteLn(StdErr, 'XkbBell request failed');
  19.   XCloseDisplay(dpy)
  20. end.
  21.  

Synchronous operation might need to be forced if dpy were derived from an existing form or application object.

As far as I can find out the named bell facility is effectively unused by this API. It is distinct from the various tones etc. that a modern desktop emits, which uses the soundcard APIs.

It's a pity that something like this isn't a standard form operation since an equivalent API appears to exist for both Windows and X11.

MarkMLl

« Last Edit: November 23, 2019, 01:18:45 pm by MarkMLl »
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.