Author Topic: Pausing channel bug? using linux arm  (Read 406 times)

aaronegger

  • Posts: 24
Pausing channel bug? using linux arm
« on: 9 Sep '21 - 14:11 »
Hi,

i have maybe a bug that prevents a channel to be paused.
Using the same code works with windows x64 fine, but fails on linux arm.

The channel is hearable playing while executing the following code.

BASSError precheck = Bass.BASS_ErrorGetCode();
BASSActive active = Bass.BASS_ChannelIsActive(CurrentHandle.Value);
bool paused = Bass.BASS_ChannelPause(CurrentHandle.Value);
BASSError error = Bass.BASS_ErrorGetCode();

precheck contains BASS_OK (0), active is BASS_ACTIVE_PLAYING (1), paused is false and error is BASS_ERROR_NOPLAY (24).
After the issue occured i debugged it by setting the breakpoint at the last line, to prevent the channel from stalling due to halting code.

Could anybody help me solving this issue?
Thank you :)

Ian @ un4seen

  • Administrator
  • Posts: 23938
Re: Pausing channel bug? using linux arm
« Reply #1 on: 9 Sep '21 - 15:52 »
Internally, the first thing BASS_ChannelPause does is call BASS_ChannelIsActive and give a BASS_ERROR_NOPLAY error if that returns 0. So the sequence of events above should be impossible unless the channel stopped between the BASS_ChannelIsActive and BASS_ChannelPause calls. Is it happening every time or only sometimes? I don't seem to be able to reproduce it here. Perhaps there's something else that needs to be done to trigger it?

Please also confirm that you're using the latest BASS version (check that with BASS_GetVersion).

aaronegger

  • Posts: 24
Re: Pausing channel bug? using linux arm
« Reply #2 on: 9 Sep '21 - 22:07 »
Hi,

thank you for this info and yes it should then be impossible, since i am doing exactly the same thing.
This issue occurs everytime for me. All i do is simple checking if the channelisactive returns "BASS_ACTIVE_PLAYING".
The user clicks on a button that triggers an async function. This function checks if the channel is playing and if so it calls the channelpause function.
On Windows it works everytime. But on raspbian it doesn't work everytime.
The version i use is 33820416 or 2.4.15.0. I downloaded the it from here https://www.un4seen.com/forum/?topic=13804.0.

The version there seems to be updated today (9.9.2021), but using the newly downloaded version doesn't work either and furthermore gives the same version number (2.4.15.0).

The version for windows is 2.4.16.7 and should be the latest one.

I have attached 3 screenshots where you can see the breakpoint and the evaluated values for the mentioned objects.
Two screenshots contain additional code to check if calling BASS_ChannelIsActive more than one time could cause this issue, but this seems to work fine.

aaronegger

  • Posts: 24
Re: Pausing channel bug? using linux arm
« Reply #3 on: 9 Sep '21 - 22:23 »
I now also tried the beta build you gave me on the 26.3.2021 ("www.un4seen.com/stuff/bass-linux-arm.zip").
Same issue and it has also the same version number (2.4.15.0).

Ian @ un4seen

  • Administrator
  • Posts: 23938
Re: Pausing channel bug? using linux arm
« Reply #4 on: 10 Sep '21 - 12:16 »
That looks like .Net/Linux is finding an older libbass.so file somewhere in the library search path and loading that rather than the later version. Where did you put the latest libbass.so file? I believe it should be alongside your app's EXE. Also make sure its architecture matches Linux's - probably "hardfp" if 32-bit, "aarch64" if 64-bit.

aaronegger

  • Posts: 24
Re: Pausing channel bug? using linux arm
« Reply #5 on: 10 Sep '21 - 13:49 »
This should be impossible, since this is the only application that has been published to a new raspbian installation.
The libs are loaded this way:
string binDir = Helper.CombinePath(Helper.GetProjectPath(), "Binaries/Bass/", OS.CurrentApplicationTarget.ToString());
//binDir is something look projectrootdir/Binaries/Bass/LinuxArm/
dlopen(Helper.CombinePath(binDir, "libbass.so"), RTLD_LAZY | RTLD_GLOBAL);
dlopen(Helper.CombinePath(binDir, "libbass_fx.so"), RTLD_LAZY);

If i delete these files the application crashes with "segmentation fault".
Therefore i am pretty sure that it loads the correct binaries (i use the hardfp version).

I will redownload them and try to extract the version with an analyzer for .so files.

aaronegger

  • Posts: 24
Re: Pausing channel bug? using linux arm
« Reply #6 on: 10 Sep '21 - 15:34 »
It didn't manage to get infos from the shared object file. I tried it with readelf but it doesn't output any information that contains any usefull version number.

So i have created a new blank test project that only tries to play and pause an mp3 file (no dsp, no fx, no sync applied) with freshly downloaded binaries.
I also tried to use the softfp and aarch64 version but both fail with "segmentation fault".

And it occurs there again. With windows x64 it works fine, but on raspbian (debian) on the raspberry pi 3 b+ it fails.

I have attached the test project. Could you verify this for me?
There is a bat file that builds a build for linux arm ("linux-arm-debug-build.bat"). Executing this should build a self contained version (no need for a runtime on the target device) at the "bin\Debug\net5.0\linux-arm" directory.
But you need the .net5 sdk to build this. I could also give a prebuilt version where you could simply swap the shared object files.

This test tool simply loads the shared object files from bass from a given directory and then starts playing a mp3 file.
After 2s it should be paused for 2s before continuing to play for another 2s.
Each step will output the result of Bass_GetErrorCode of the predecessing task.
And it also outputs the version number of the loaded binaries (libbass and libbassfx).
I have included libbassfx because it is used at the main project too, although no function except the one to get the version is used at this test project.

On windows i have following output:
2.4.16.7
2.4.12.1
BASS_StreamCreateFile: BASS_OK
BASS_ChannelPlay: BASS_OK
BASS_ChannelPause: BASS_OK
BASS_ChannelPlay: BASS_OK

On the raspberry pi i get following output:
2.4.15.0
2.4.12.1
BASS_StreamCreateFile: BASS_OK
BASS_ChannelPlay: BASS_OK
BASS_ChannelPause: BASS_ERROR_NOPLAY
BASS_ChannelPlay: BASS_OK

Could you maybe provide me the latest build of the arm version?
Maybe something didn't work correctly while updating the post with the link to the arm version.
Maybe i get a cached file from a cdn that doesn't work correctly.
I tried to download it again with some query parameter to try preventing downloading cached files, but i always get the same version.

Ian @ un4seen

  • Administrator
  • Posts: 23938
Re: Pausing channel bug? using linux arm
« Reply #7 on: 10 Sep '21 - 16:17 »
That looks like it is the latest "hardfp" libbass.so file (released a couple days ago) in your test package. I checked the BASS_GetVersion return value here (in C/C++ rather than .Net) and it's 0x02041007 (2.4.16.7). So it still looks most like another libbass.so file is getting loaded in your test there. Can you try removing the dlopen calls and instead putting the latest libbass.so file alongside your app's EXE, and see if .Net loads it then?

aaronegger

  • Posts: 24
Re: Pausing channel bug? using linux arm
« Reply #8 on: 10 Sep '21 - 16:33 »
Sadly this is not possible. It tried some day ago but there was an issue using bassfx.
Maybe you remember this thread: https://www.un4seen.com/forum/?topic=19311

Your anwser back then was:
"I believe .Net loads a library upon its first use, so you can get BASS loaded before BASS_FX by simply making sure a BASS function is called first, eg. perhaps BASS_GetVersion.

But I believe there's also another issue now when using BASS with .Net Core, in that it doesn't load libraries with global scope, so the add-ons can't see the BASS functions. That was one thing that motivated the change mentioned in my last post. In the meantime, if simply calling a BASS function first isn't working for you then you can try using dlopen to give the BASS functions global scope, as described here:

   www.un4seen.com/forum/?topic=13804.msg133116#msg133116"

I am forced to use dlopen.
But why does dlopen fail if i delete the libbass.so file that i expect it to load?

I can try to copy the whole application to another raspberry pi (not same same, its the 4th gen). This pi never saw any app using bass.
I will report which result i got.


aaronegger

  • Posts: 24
Re: Pausing channel bug? using linux arm
« Reply #9 on: 10 Sep '21 - 16:53 »
Ok this seems to be the right track.
dlopen may load the lib but the shared object file is loaded from somewhere else (but i don't know from where).
Since the LoadMe function does only work on windows due to the dependency to kernel32.dll i have to figure it out how to get the file loaded from a specific directory..
Copying the libs to the root folder of the application allows to load the right version.

But this doesn't fix the pausing issue.

This is my result on the raspberry pi model 3b+:
pi@raspi:/srv/raspi/development/basstest $ ./BassLibArmTestBugDeleteMe
2.4.16.7
2.4.12.1
BASS_StreamCreateFile: BASS_OK
BASS_ChannelPlay: BASS_OK
BASS_ChannelPause: BASS_ERROR_NOPLAY
BASS_ChannelPlay: BASS_OK

Version is now the correct one, but pausing doesn't work with this version too.

On the raspberry pi 4 i get the same result:

pi@MerlinPi:/srv/test stuff/basstest $ ./BassLibArmTestBugDeleteMe
2.4.16.7
2.4.12.1
BASS_StreamCreateFile: BASS_OK
BASS_ChannelPlay: BASS_OK
BASS_ChannelPause: BASS_ERROR_NOPLAY
BASS_ChannelPlay: BASS_OK

aaronegger

  • Posts: 24
Re: Pausing channel bug? using linux arm
« Reply #10 on: 10 Sep '21 - 17:12 »
I tried to use it without dlopen.
As expected the call of BASS_FX_GetVersion() then fails with "Segmentation fault".
If i remove this call it works.

Then i get this result:
2.4.16.7
BASS_StreamCreateFile: BASS_OK
BASS_ChannelPlay: BASS_OK
BASS_ChannelPause: BASS_OK
BASS_ChannelPlay: BASS_OK

But this doesn't fix the issue too.
Since now i am not able to use the bassfx lib. But i need it.
I need both. Pausing funciton and fx.

But why is everything else working, play, stop, dsp, sync etc. But only calling pause fails.
I don't understand whats going on here..

Ian @ un4seen

  • Administrator
  • Posts: 23938
Re: Pausing channel bug? using linux arm
« Reply #11 on: 10 Sep '21 - 17:56 »
Good to hear that the correct libbass.so version is being loaded now. I suspect the issue was that .Net wasn't using the libbass.so file that you had loaded via dlopen, and was instead loading whatever libbass.so file could be found in the library search path (apparently there's an old libbass.so somewhere in there). For the dlopen/RTLD_GLOBAL trick to work, it needs to be on the same file that .Net is loading. For example, like this should work:

Code: [Select]
Bass.BASS_GetVersion(); // call/load BASS
dlopen("libbass.so", RTLD_NOLOAD | RTLD_GLOBAL | RTLD_LAZY); // give global scope to its functions

But I'll get an updated BASS_FX build that links to BASS (instead of relying on it already being loaded with global scope) for you on Monday, which will hopefully mean you don't need to bother with this dlopen business.

Ian @ un4seen

  • Administrator
  • Posts: 23938
Re: Pausing channel bug? using linux arm
« Reply #12 on: 13 Sep '21 - 12:58 »
Here's the BASS_FX update that links with the BASS library:

   www.un4seen.com/stuff/bass_fx-linux-arm.zip

Let me know if you still have the problem when using that without the dlopen trick.

aaronegger

  • Posts: 24
Re: Pausing channel bug? using linux arm
« Reply #13 on: 20 Sep '21 - 11:34 »
Sorry, i was not at home this week.
But i have tested it now and can confirm that it now works without dlopen.
I ran the program with the last version version and it crashed with "Segmentation fault".
After replacing it with the new version you provided (i used the hardfp version 2.4.12.5) it worked.

Thank you for this update :)

Now i only have to figure out how to load the library from another folder.
If i find a solution for that i will post it here.

aaronegger

  • Posts: 24
Re: Pausing channel bug? using linux arm
« Reply #14 on: 20 Sep '21 - 18:04 »
I didn't find the desired solution.
Loading the library with dlopen will load the current library, but it is not recognized as the correct dependency for example for bassfx.
Linux tries to find the shared object file of the bass lib without using the already loaded library.

So instead of trying to load from a specific path, i simply configured the csproj file to copy the libraries that are required for the selected runtime to the root output path.

For anyone who is trying to do the same you could use something like this.
This works also great with the packaging tool to publish directly to debian files (qmfrederik/dotnet-packaging)

Code: [Select]

<Target Name="CopyBassWin86" AfterTargets="AfterBuild" Condition="$(RuntimeIdentifier.StartsWith('win')) And $(RuntimeIdentifier.EndsWith('86'))">
<ItemGroup>
<_CopyWin86 Include="Binaries\Bass\WindowsX86\*.dll" />
</ItemGroup>
<Copy SourceFiles="@(_CopyWin86)" DestinationFolder="$(OutDir)" />
</Target>
<Target Name="CopyBassWin86Publish" AfterTargets="Publish" Condition="$(RuntimeIdentifier.StartsWith('win')) And $(RuntimeIdentifier.EndsWith('86'))">
<ItemGroup>
<_CopyWin86 Include="Binaries\Bass\WindowsX86\*.dll" />
</ItemGroup>
<Copy SourceFiles="@(_CopyWin86)" DestinationFolder="$(PublishDir)" />
</Target>

<Target Name="CopyBassWin64" AfterTargets="AfterBuild" Condition="$(RuntimeIdentifier.StartsWith('win')) And $(RuntimeIdentifier.EndsWith('64'))">
<ItemGroup>
<_CopyWin64 Include="Binaries\Bass\WindowsX64\*.dll" />
</ItemGroup>
<Copy SourceFiles="@(_CopyWin64)" DestinationFolder="$(OutDir)" />
</Target>
<Target Name="CopyBassWin64Publish" AfterTargets="Publish" Condition="$(RuntimeIdentifier.StartsWith('win')) And $(RuntimeIdentifier.EndsWith('64'))">
<ItemGroup>
<_CopyWin64 Include="Binaries\Bass\WindowsX64\*.dll" />
</ItemGroup>
<Copy SourceFiles="@(_CopyWin64)" DestinationFolder="$(PublishDir)" />
</Target>

<Target Name="CopyBassLinuxArm" AfterTargets="AfterBuild" Condition="$(RuntimeIdentifier) == 'linux-arm'">
<ItemGroup>
<_CopyLinuxArm Include="Binaries\Bass\LinuxArm\*.so" />
</ItemGroup>
<Copy SourceFiles="@(_CopyLinuxArm)" DestinationFolder="$(OutDir)" />
</Target>
<Target Name="CopyBassLinuxArmPublish" AfterTargets="Publish" Condition="$(RuntimeIdentifier) == 'linux-arm'">
<ItemGroup>
<_CopyLinuxArm Include="Binaries\Bass\LinuxArm\*.so" />
</ItemGroup>
<Copy SourceFiles="@(_CopyLinuxArm)" DestinationFolder="$(PublishDir)" />
</Target>

Thank you very much Ian for helping me solving this :D