How to do audio output selection for MediaPlayer control?
Posted
#1
(In Topic #478)
Regular

Issue #1:
There seems to be a little bit of strange behavior while working on a Raspberry Pi 4. Every third or fourth play or so the playback halts. The event handler reports an event type 1. I was able to code a work around (will be included when I post it in the project showcase) that stops the player, resets the URL, then starts the player again when this event occurs. The only consequence is the song gets listed twice in the history. Rather than fixing that, I let it be so I could track occurrences.
Issue #2:
The media player does not honor the default audio out system setting. Strangely it works opposite on the Pi4 than my Mint laptop. When I plug in an external usb sound device it takes precedence on the laptop while on the Pi4 the HDMI output takes precedence.
So, I looked at the wiki at the media player stuff and am a bit puzzled at how to put it all together. I was hoping somebody has already done this and knows the proper way to do it.
I'd like to add a settings tab to the player that lets the output channel be selected on the fly. This requires being able to read the available outputs and then being able to select one.
Does anyone know how to do this?
.... and carry a big stick!
Posted
Regular

However, in general if you want to identify the audio device, to which to direct the audio, in my opinion you have to use the ".Audio.Output" Property of the "MediaPlayer" Class, assigning it the GStreamer plugin - for example - "alsasink" through the "MediaControl" Class and specifying the audio-device.
I show a practical example:
Code (gambas)
Europaeus sum !
<COLOR color="#FF8000">Amare memorentes atque deflentes ad mortem silenter labimur.</COLOR>
<COLOR color="#FF8000">Amare memorentes atque deflentes ad mortem silenter labimur.</COLOR>
Posted
Regular

hw:0 plays through the laptops internal speaker, not the HDMI.
This code snippet:
Generates this output:
Code
source filesrc
audiosink autoaudiosink
I've been doing some searching on ALSA, and found the following:
Code
~ $ aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: MID [HDA Intel MID], device 0: ALC269VB Analog [ALC269VB Analog]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 0: MID [HDA Intel MID], device 3: HDMI 0 [HDMI 0]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 0: MID [HDA Intel MID], device 7: HDMI 1 [HDMI 1]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: MiniLink [MiniLink], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0
~ $ cat /proc/asound/modules
0 snd_hda_intel
1 snd_usb_audio
~ $ cat /proc/asound/cards
0 [MID ]: HDA-Intel - HDA Intel MID
HDA Intel MID at 0xd4620000 irq 45
1 [MiniLink ]: USB-Audio - MiniLink
XITEL MiniLink at usb-0000:00:1d.0-1.3.6, full speed
So, now I'm trying to tie it all together. Still unsuccessful, but better off than I was before.
.... and carry a big stick!
Posted
Regular

…I used "alsasink" plugin, not autoaudiosink.Cedron said
Code
source filesrc
audiosink autoaudiosink
Cedron said
Code
~ $ aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: MID [HDA Intel MID], device 0: ALC269VB Analog [ALC269VB Analog]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 0: MID [HDA Intel MID], device 3: HDMI 0 [HDMI 0]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 0: MID [HDA Intel MID], device 7: HDMI 1 [HDMI 1]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: MiniLink [MiniLink], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0
Did you try with: <COLOR color="#800000">"hw:0,3,0"</COLOR> or <COLOR color="#800000">"hw:0,7,0"</COLOR> ?
Europaeus sum !
<COLOR color="#FF8000">Amare memorentes atque deflentes ad mortem silenter labimur.</COLOR>
<COLOR color="#FF8000">Amare memorentes atque deflentes ad mortem silenter labimur.</COLOR>
Posted
Regular

From looking at /etc/share/alsa/alsa.conf, I've also tried using "subdevice" on another line and get "Unknown property".
On my mint box, I can switch outputs while the player is playing through the sound preferences. This is adequate for my needs, but it doesn't work that way on the Pi4.
Strange.
.... and carry a big stick!
Posted
Regular

My laptop also has the HDMI device, and it is identified with card 0, device 3 and subdevice 0.Cedron said
All give me a "Can't set Status" error when the .play is hit.
So, I tried that code of mine with these instructions:
About GStreamer plugins - used in 2nd argument of MediaControl object - and their properties, you can have a look here:Cedron said
I've also tried using "subdevice" on another line and get "Unknown property".
Plugins
Europaeus sum !
<COLOR color="#FF8000">Amare memorentes atque deflentes ad mortem silenter labimur.</COLOR>
<COLOR color="#FF8000">Amare memorentes atque deflentes ad mortem silenter labimur.</COLOR>
Posted
Regular

That is a helpful link. The default created by ".play" is obviously "autoalsosink" which allows the system preferences to switch output during playback on my laptop, but not the Pi4. When a media control is explicitly create, per your code, then the playback is immune to the system setting. This is what I wanted.
Now I have to incorporate it into my music player. Do you know of any "pure Gambas" way via the Media* controls of getting the equivalent of the "aplay -l" output?
I do know how to shell, capture, and parse.
Thanks again.
In case anybody hasn't seen it, my music player is available here:
Gambas One - Gambas ONE
"It's the best ever, nobody has ever seen anything like it."
.... and carry a big stick!
Posted
Regular

Well, I can show you this page, that I wrote, of the WIKI of the Gambas Italian programmers forum.Cedron said
Do you know of any "pure Gambas" way via the Media* controls of getting the equivalent of the "aplay -l" output?
There you can try two codes, which however use the external functions of ALSA via "Extern ":
Conoscere con le funzioni esterne di ALSA i dispositivi audio presenti nel sistema - Gambas-it.org - Wikipedia
…but if you don't want to use the external ALSA functions, you can easily get those string data from the files in the subfolders of "/proc/asound/ " path.
And more, If you still prefer to use the resources of the gb.media Component, you need to search through the appropriate properties of GStreamer plugins, and use them with the MediaControl Object.
Europaeus sum !
<COLOR color="#FF8000">Amare memorentes atque deflentes ad mortem silenter labimur.</COLOR>
<COLOR color="#FF8000">Amare memorentes atque deflentes ad mortem silenter labimur.</COLOR>
Posted
Regular

Thanks to your help, I don't have to do that. The /proc/asound/pcm file, loaded with a single File.Load statement does the trick. I've added a "Settings" tab to the music player and put a list box there with the lines from that file. On a click, I can consruct the proper hw: argument and good to go. The only thing is that it needs to be done before the player is started. That's not a problem for me, but something I need to fix before I post the upgrade. That is going to have to wait for another day.
It still concerns me that the MediaPlayer doesn't honor the system setting on the Pi4. I'm not sure whether it is worth reporting as a bug (It is 3.12.2 after all). Perhaps somebody else who has a Pi4 can verify the same problem.
Many thanks again.
.... and carry a big stick!
Posted
Regular

I have run into an issue whereby I am trying to get audio samples from the Media Viewer or a sound device input.
Option 1
Is to find away to do this from the Media Viewer and to convert it to a lower PCM format of 22.05 kHz, stereo at 8bit sizes, to send to a Byte or an Integer to work with.
Option 2
If this can not be done, to read in the samples from a sound device at 22.05 kHz, stereo at 8bits to send to a Byte or an Integer to work with.
The last step would be to send this processed audio back out to sound device, any ideas on how this could done within Gambas?
I have been trying to do something like this for a few weeks now.
Posted
Regular

In general with gb.media Component, to change audio characteristics of a file, during its conversion, the MediaPipeline and MediaFilter Classes should be used.GrantXTV said
Option 2
If this can not be done, to read in the samples from a sound device at 22.05 kHz, stereo at 8bits to send to a Byte or an Integer to work with.
Below is a practical example, in which we convert an MP3 file to a WAV file having sample rate = 22050 hertz and resolution = 8 bit:
Code (gambas)
- temporaneo = Temp
- audiofile = "/path/of/audio/file/we/want/covert"
- src["location"] = audiofile
- res = New MediaControl(pl, "audioresample") ' Allows to change the characteristics of the audio file
- flt = New MediaFilter(pl, "audio/x-raw,rate=22050,format=U8") ' Set the characteristics of the audio file
- snk["location"] = temporary
- src.LinkTo(dcb)
- dcb.LinkLaterTo(con)
- con.LinkTo(res)
- res.LinkTo(flt)
- flt.LinkTo(wav)
- wav.LinkTo(snk)
- pl.play
- Wait 0.01
- Wait 0.01
- Until bo
- pl.Close
- Print "\n\e[0mEnd conversion !"
- bo = True
Code (gambas)
Europaeus sum !
<COLOR color="#FF8000">Amare memorentes atque deflentes ad mortem silenter labimur.</COLOR>
<COLOR color="#FF8000">Amare memorentes atque deflentes ad mortem silenter labimur.</COLOR>
Posted
Regular

Tested on gstreamer
gst-launch-1.0 alsasrc ! audioconvert ! audio/x-raw,rate=48000,depth=8,channels=2,width=16 ! rtpL24pay ! udpsink host=192.168.3.15 port=5001
Public bo As Boolean
Public Sub Form_Open()
bo = True
End
Public Sub send_Click()
Dim pl As MediaPipeline
Dim src, aco, wen, snk, rtp, udp As MediaControl
Dim flt As MediaFilter
pl = New MediaPipeline
src = New MediaControl(pl, "alsasrc")
aco = New MediaControl(pl, "audioconvert")
flt = New MediaFilter(pl, "audio/x-raw,rate=44100,depth=16,channels=2,width=16,signed=true")
rtp = New MediaControl(pl, "rtpL24pay")
udp = New MediaControl(pl, "udpsink host=192.168.3.15 port=5001")
src.LinkTo(aco)
aco.LinkTo(flt)
flt.LinkTo(rtp)
rtp.LinkTo(udp)
pl.Play()
While bo
TextBox1.Text = Str(Time(0, 0, 0, pl.Position * 1000))
Wait 0.01
Wend
pl.Stop()
pl.Close()
Quit
End
Public Sub stop_Click()
bo = False
End
Public Sub Form_Close()
bo = False
End
Posted
Regular

"HOST" and "PORT" are properties of the "udpsink " GStreamer Plugin.GrantXTV said
udp = New MediaControl(pl, "udpsink host=192.168.3.15 port=5001")
Therefore they should be highlighted and separated.
……
udp = New MediaControl(pl, "udpsink")
udp["host"] = "192.168.3.15"
udp["port"] = 5001
……
If you want to use "gst-launch-1.0 ", you will have to use its corresponding external function "gst_parse_launch()", since it has not been implemented in the Gambas gb.media Component.GrantXTV said
This is what I tested on gstreamer and it works:
'gst-launch-1.0 alsasrc ! audioconvert ! audio/x-raw,rate=48000,depth=8,channels=2,width=16 ! rtpL24pay ! udpsink host=192.168.3.15 port=5001
What is best way to do this using mediaview, as I have not found a way to get this to work?
Exemplum:
https://www.gambas-it.org/wiki/index.php/Eseguire_un_file_audio_usando_una_linea_di_pipeline_con_la_funzione_%27gst_parse_launch()%27
Europaeus sum !
<COLOR color="#FF8000">Amare memorentes atque deflentes ad mortem silenter labimur.</COLOR>
<COLOR color="#FF8000">Amare memorentes atque deflentes ad mortem silenter labimur.</COLOR>
Posted
Regular

I have tested this code out and it works, but there is an issues with the audio cutting in and out, I may need to add some type of audio buffer.
Any ideas on how I can go about this?
Other than this I can now look at doing the receiver part:
gst-launch-1.0 -v udpsrc port=5001 ! 'application/x-rtp,media=audio,payload=96,clock-rate=44100,channels=2,encoding-name=L24' ! rtpL24depay ! audioconvert ! autoaudiosink sync=false
Posted
Regular

Posted
Regular

…this does not seem to be difficult.GrantXTV said
Other than this I can now look at doing the receiver part:
gst-launch-1.0 -v udpsrc port=5001 ! 'application/x-rtp,media=audio,payload=96,clock-rate=44100,channels=2,encoding-name=L24' ! rtpL24depay ! audioconvert ! autoaudiosink sync=false
Europaeus sum !
<COLOR color="#FF8000">Amare memorentes atque deflentes ad mortem silenter labimur.</COLOR>
<COLOR color="#FF8000">Amare memorentes atque deflentes ad mortem silenter labimur.</COLOR>
Posted
Regular

Today's work on the receiver part, "this does not seem to be difficult", but it is not easy, as I have found that issues is with the flt.LinkTo(rtp) part, I am not sure what is going on here.
gst-launch-1.0 udpsrc port=5004 ! application/x-rtp,media=audio,payload=96,clock-rate=41000,depth=8,channels=2,signed=true,encoding-name=L24 ! rtpL24depay ! audioconvert ! autoaudiosink sync=false
This is where I started with testing this script, but translation it to media player as be low:
Public bo As Boolean
Public Sub Form_Open()
bo = True
End
Public Sub Play_Click()
Dim pl As MediaPipeline
Dim src, rtp, aco, als As MediaControl
Dim flt As MediaFilter
pl = New MediaPipeline
src = New MediaControl(pl, "udpsrc")
src["port"] = "5004"
flt = New MediaFilter(pl, "application/x-rtp,media=audio,payload=96,clock-rate=41000,depth=8,channels=2,signed=true,encoding-name=L24")
rtp = New MediaControl(pl, "rtpL24pay")
aco = New MediaControl(pl, "audioconvert")
als = New MediaControl(pl, "autoaudiosink")
als["sync"] = "false"
src.LinkTo(flt)
flt.LinkTo(rtp)
rtp.LinkTo(aco)
aco.LinkTo(als)
pl.Play()
While bo
'Write "\rTempo: " & Str(Time(0, 0, 0, pl.Position * 1000))
TextBox1.Text = Str(Time(0, 0, 0, pl.Position * 1000))
Wait 0.01
Wend
pl.Stop()
pl.Close()
Quit
End
Public Sub stop_Click()
bo = False
End
Public Sub Form_Close()
bo = False
End
Maybe I am missing something?
Posted
Regular

……
flt.<COLOR color="#800000">LinkLaterTo</COLOR>(rtp)
rtp.<COLOR color="#800000">LinkLaterTo</COLOR>(aco)
……
Europaeus sum !
<COLOR color="#FF8000">Amare memorentes atque deflentes ad mortem silenter labimur.</COLOR>
<COLOR color="#FF8000">Amare memorentes atque deflentes ad mortem silenter labimur.</COLOR>
Posted
Regular

** (URL_Player:719423): CRITICAL **: 10:20:16.200: gst_capsfilter_prepare_buf: assertion 'out_caps != NULL' failed
I have been looking around on the internet to see what this could be, but nothing so far, any ideas?
Posted
Regular

…but does the code work ?
Is it a simple warning or critical.. fatal error ?
Europaeus sum !
<COLOR color="#FF8000">Amare memorentes atque deflentes ad mortem silenter labimur.</COLOR>
<COLOR color="#FF8000">Amare memorentes atque deflentes ad mortem silenter labimur.</COLOR>
Posted
Regular

I reworked the code for the UDP Receiver and that seemed to get it to work okay, there is one small issue with the UDP Transmitter, but it works well enough.
Here is the Transmitter:
Public bo As Boolean
Public pl As MediaPipeline
Public Sub Form_Open()
bo = True
End
Public Sub send_Click()
Dim src, aco, wen, snk, rtp, udp As MediaControl
Dim flt As MediaFilter
bo = True
pl = New MediaPipeline
src = New MediaControl(pl, "alsasrc")
aco = New MediaControl(pl, "audioconvert")
flt = New MediaFilter(pl, "audio/x-raw,rate=41000,depth=8,channels=2,signed=true")
rtp = New MediaControl(pl, "rtpL24pay")
udp = New MediaControl(pl, "udpsink")
udp["host"] = "192.168.3.15"
udp["port"] = "5004"
src.LinkTo(aco)
aco.LinkTo(flt)
flt.LinkTo(rtp)
rtp.LinkTo(udp)
pl.Play()
While bo
TextBox1.Text = Str(Time(0, 0, 0, pl.Position * 1000))
Wait 0.01
Wend
End
Public Sub stop_Click()
pl.Stop()
bo = False
End
Public Sub Form_Close()
pl.Stop()
pl.Close()
bo = False
End
Here is what works for the Receiver:
Public bo As Boolean
Public pl As MediaPipeline
Public Sub Form_Open()
Dim src, rtp, aco, als As MediaControl
Dim flt As MediaFilter
pl = New MediaPipeline
src = New MediaControl(pl, "udpsrc")
src["port"] = "5004"
flt = New MediaFilter(pl, "application/x-rtp,media=audio,payload=96,clock-rate=41000,depth=8,channels=2,signed=true,encoding-name=L24")
rtp = New MediaControl(pl, "rtpL24depay")
aco = New MediaControl(pl, "audioconvert")
als = New MediaControl(pl, "autoaudiosink")
als["sync"] = "false"
src.LinkTo(flt)
flt.LinkTo(rtp)
rtp.LinkTo(aco)
aco.LinkTo(als)
pl.Pause
End
Public Sub Play_Click()
pl.Play()
bo = True
While bo
TextBox1.Text = Str(Time(0, 0, 0, pl.Position * 1000))
Wait 0.01
Wend
End
Public Sub stop_Click()
pl.Pause()
pl.Stop()
bo = False
End
Public Sub Form_Close()
pl.Stop()
pl.Close()
bo = False
End
With the UDP receiver I found that I needed to use a work around by using pause then stop, or the the software could crash.
From this experimenting, I workout that the the MediaPlayer has four input / output states:
Hardware
File
IP / UDP
Jack Audio
The Jack Audio is something I may look at as well, at later date as could be useful, but the IP streaming is important one right now.
1 guest and 0 members have just viewed this.



