How to free the players for real ?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
60 messages Options
123
Reply | Threaded
Open this post in threaded view
|

How to free the players for real ?

jeremzw
Hello,

I'm experiencing a problem with freeing the players on a lazarus project I made. (Lazarus 1.6.4 on Linux Mint 19)
The project is a jukebox playing music tracks in a playlist. (mp3, flac...)

This is the way I'm loading the players :

uos_CreatePlayer(nPlayer); /// you may create how many players you want, from 0 to to what you computer can do...
uos_AddIntoDevOut(nPlayer);   //// Add Output with default parameter
InputIndex1 := uos_AddFromFile(nPlayer, PChar(LePath));
uos_InputSetPositionEnable(nPlayer, InputIndex1, 1) ;
uos_AddDSPVolumeIn(nPlayer, inputIndex1, 1, 1);
uos_InputSetLevelEnable(nPlayer, InputIndex1, 3) ;

And when the sound was played, here's what I do to free it (after checking with uos_getstatus) :
uos_stop(nPlayer);

Now the problem is that after a while, the program takes a lot of memory.
When I check the sound control, here's what I see :
sound

It seems that the players never disappear from the list even though they're freed. (And I'm only loading a maximum of 5 players, that I'm supposed to reuse...)

Anyone would please know why it's so, and how I can free them for real ? Thanks !






 
Reply | Threaded
Open this post in threaded view
|

Re: How to free the players for real ?

fredvs
Administrator
This post was updated on .
Hello.

What command do you use to play ?

If you use:  uos_Play(nPlayer)  then all memory is freed after uos_Stop(nPlayer) or when the song reach the end.

Tested here with the DJ console of Strumpract (https://github.com/fredvs/strumpract/releases).

When stopping a player, the thread in the Output-control of ALSA manager is closed too.

[EDIT] Here video that demonstrate it:
https://sites.google.com/site/fredvsbinaries/fuos_threads.mp4

Maybe if you show more code?

Fre;D
Reply | Threaded
Open this post in threaded view
|

Re: How to free the players for real ?

jeremzw
This post was updated on .
Hello Fred,

thanks for your reply.
Sure, I can show you more code. I do use uos_play, that's why I don't understand...

So, when the form is activated :

procedure TForm1.FormActivate(Sender: TObject);
var
  ordir: string;
  PortAudioFileName: string;
  SndFileFileName: string;
  Mpg123FileName: string;
  Mp4ffFileName: string;
  FaadFileName: string;
{$IFDEF Darwin}
  opath: string;
{$ENDIF}

begin
  ordir := application.Location;
  //uos_logo();
             {$IFDEF Windows}
     {$if defined(cpu64)}
  PortAudioFileName := ordir + 'lib\Windows\64bit\LibPortaudio-64.dll';
  SndFileFileName := ordir + 'lib\Windows\64bit\LibSndFile-64.dll';
  Mpg123FileName := ordir + 'lib\Windows\64bit\LibMpg123-64.dll';
  //Edit5.Text := ordir + 'lib\Windows\64bit\plugin\LibSoundTouch-64.dll';
{$else}
  PortAudioFileName := ordir + 'lib\Windows\32bit\LibPortaudio-32.dll';
  SndFileFileName := ordir + 'lib\Windows\32bit\LibSndFile-32.dll';
  Mpg123FileName := ordir + 'lib\Windows\32bit\LibMpg123-32.dll';
  Mp4ffFileName := ordir + 'lib\Windows\32bit\LibMp4ff-32.dll';
  FaadFileName := ordir + 'lib\Windows\32bit\LibFaad2-32.dll';
  //Edit5.Text := ordir + 'lib\Windows\32bit\plugin\LibSoundTouch-32.dll';
  //Edit6.Text := ordir + 'lib\Windows\32bit\plugin\Libbs2b-32.dll';
   {$endif}

 {$ENDIF}

 {$IFDEF freebsd}
    {$if defined(cpu64)}
    PortAudioFileName := ordir + 'lib/FreeBSD/64bit/libportaudio-64.so';
     SndFileFileName := ordir + 'lib/FreeBSD/64bit/libsndfile-64.so';
    Mpg123FileName := ordir + 'lib/FreeBSD/64bit/libmpg123-64.so';
    //Edit5.Text := '' ;
    //Edit6.text := ordir + 'lib/FreeBSD/64bit/plugin/libbs2b-64.so';

    {$else}
   PortAudioFileName := ordir + 'lib/FreeBSD/32bit/libportaudio-32.so';
     SndFileFileName := ordir + 'lib/FreeBSD/32bit/libsndfile-32.so';
    Mpg123FileName := ordir + 'lib/FreeBSD/32bit/libmpg123-32.so';
     //Edit5.Text := '' ;
{$endif}

 {$ENDIF}

  {$IFDEF Darwin}
  opath := ordir;
  opath := copy(opath, 1, Pos('/uos', opath) - 1);
  PortAudioFileName := opath + '/lib/Mac/32bit/LibPortaudio-32.dylib';
  SndFileFileName := opath + '/lib/Mac/32bit/LibSndFile-32.dylib';
  Mpg123FileName := opath + '/lib/Mac/32bit/LibMpg123-32.dylib';
  //Edit5.Text := opath + '/lib/Mac/32bit/plugin/LibSoundTouch-32.dylib';

            {$ENDIF}

   {$IFDEF linux}
    {$if defined(cpu64)}
  PortAudioFileName := ordir + 'lib/Linux/64bit/LibPortaudio-64.so';
  SndFileFileName := ordir + 'lib/Linux/64bit/LibSndFile-64.so';
  Mpg123FileName := ordir + 'lib/Linux/64bit/LibMpg123-64.so';
  Mp4ffFileName := ordir + 'lib/Linux/64bit/LibMp4ff-64.so';
  FaadFileName := ordir + 'lib/Linux/64bit/LibFaad2-64.so';
  //Edit5.Text := ordir + 'lib/Linux/64bit/plugin/LibSoundTouch-64.so';
  //Edit6.Text := ordir + 'lib/Linux/64bit/plugin/libbs2b-64.so';
{$else}
  PortAudioFileName := ordir + 'lib/Linux/32bit/LibPortaudio-32.so';
  SndFileFileName := ordir + 'lib/Linux/32bit/LibSndFile-32.so';
  Mpg123FileName := ordir + 'lib/Linux/32bit/LibMpg123-32.so';
  Mp4ffFileName := ordir + 'lib/Linux/32bit/LibMp4ff-32.so';
  FaadFileName := ordir + 'lib/Linux/32bit/LibFaad2-32.so';
  //Edit5.Text := ordir + 'lib/Linux/32bit/plugin/LibSoundTouch-32.so';
  //Edit6.Text := ordir + 'lib/Linux/32bit/plugin/libbs2b-32.so';
{$endif}

            {$ENDIF}

  //opendialog1.Initialdir := application.Location + 'sound';
 uos_LoadLib(PChar(PortAudioFileName), PChar(SndFileFileName), PChar(Mpg123FileName),  PChar(Mp4ffFileName), PChar(FaadFileName));


end;





when a sound is "on air", the 3 next sounds are loaded :

Function ChargePlayer(LePath: string):integer;
var
   n: integer;
   nPlayer: integer;
   nStatus : integer;
   s: string;
begin
     result:=-1;
     For nPlayer:=1 to 5 do
          begin
               /////// Get the status of the player : -1 => error, 0 => has stopped, 1 => is running, 2 => is paused.
          s:= s + inttostr(nPlayer) + ' : ' + inttostr(uos_GetStatus(nPlayer)) + ' / ';
          if (uos_GetStatus(nPlayer) <> 1) And (Numligne(nPlayer) = -1) then
              begin
                   uos_CreatePlayer(nPlayer); /// you may create how many players you want, from 0 to to what you computer can do...
                   uos_AddIntoDevOut(nPlayer);   //// Add Output with default parameter
                   If Fileexists(LePath) then
                     begin
                          result:=nPlayer;
                          InputIndex1 := uos_AddFromFile(nPlayer, PChar(LePath));
                          uos_InputSetPositionEnable(nPlayer, InputIndex1, 1) ;
                          uos_AddDSPVolumeIn(nPlayer, inputIndex1, 1, 1);
                          uos_InputSetLevelEnable(nPlayer, InputIndex1, 3) ;
                     end;
                   break;
              end;
          end;
end;


When the "on air" sound has reached its end, the next one is played, I'm calling this procedure :

Procedure PlaySon(nLigne: integer);
var
   nPlayer: integer;
   samformat: shortint;
   temptime: ttime;
   ho, mi, se, ms: word;
begin
     If Form1.GridProg.Cells[6,nLigne]<>'' then
       begin
            nPlayer:=strtoint(Form1.GridProg.Cells[6,nLigne]);
            uos_Play(nPlayer);
            temptime:= uos_InputLengthTime(nPlayer, inputIndex1 );
            DecodeTime(temptime, ho, mi, se, ms);
            Form1.labeltot.tag:= integer(mi + 1000*se + 60000*mi + 3600000*ho);
            Form1.LabelTOT.caption:= format('%.2d:%.2d:%.2d.%.3d', [ho, mi, se, ms]);

       end;
end;


Within a timer procedure, I check if the previous sound stopped with uos_getstatus.
When one is stopped, I try to free the player with uos_stop(nPlayer);

And when the program is closed :

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: boolean);
begin
  if uos_getstatus(0) = 1 then uos_stop(0);
  if uos_getstatus(1) = 1 then uos_stop(1);
  uos_UnloadPlugin('soundtouch');
  uos_UnloadPlugin('bs2b');
  uos_UnloadLib();
end;      






Reply | Threaded
Open this post in threaded view
|

Re: How to free the players for real ?

fredvs
Administrator
This post was updated on .
Hello.

Please take a look at MorseTL.lpi project /fred/uos/examples/morseTL.lpr.

It uses the "EndProc" feature. "EndProc" is the method that is assigned when a song  stop.

I do not understand why you want to prepare 5 songs.

[EDIT] You should not use a timer for checking if song is ended, use EndProc instead.

Fre;D
Reply | Threaded
Open this post in threaded view
|

Re: How to free the players for real ?

fredvs
Administrator
Hello.

The reason while the prepared songs are not released from memory after stop() is because you did not play/pause the song before to stop it.

Could you, please, try with last uos commit: 270082b...0f453d5 ?
https://github.com/fredvs/uos/

Thanks to note this and sorry for the disagreement.

PS: I still think that you should use EndProc() instead of a timer + uos_GetStatus().

Fre;D

Reply | Threaded
Open this post in threaded view
|

Re: How to free the players for real ?

jeremzw
Hello !

I tried the new uos.pas, and nothing changed. (The Alsa window never gets rid of the old songs)

Well, the prepared songs are played.
I think they just stop naturally when they end.
And then the timer checks if the status is -1 to make sure they were freed with stop().

Do you mean this is not enough and I should use EndProc() then ?

Ok, I'll look up this project link you sent and try to use it then.
Reply | Threaded
Open this post in threaded view
|

Re: How to free the players for real ?

jeremzw
I tried the Morse.lpi after saving the 5 Morse* files in one folder, but it wouldn't open in Lazarus :

Impossible to read the file :"/home/jeremie/Téléchargements/morse/morseTL.lpi".
In 'stream:' (line 44 pos 91): Expected "="
Reply | Threaded
Open this post in threaded view
|

Re: How to free the players for real ?

jeremzw
Oh, I just figured out that my project was not using uos.pas but uos_flat.pas ...

Maybe that's the key ? What's the difference between both ?
Reply | Threaded
Open this post in threaded view
|

Re: How to free the players for real ?

jeremzw
Please ignore what I said about Morse... I just forgot to log in so the .pas were in html...

So here's what I tried :
I replaced the procedure uos_stop in uos_flat to have this :

procedure uos_Stop(PlayerIndex: cint32);// Stop playing and if uos_Play() was used: free the player
begin
  if (length(uosPlayers) > 0) and (PlayerIndex +1 <= length(uosPlayers)) then
  if  uosPlayersStat[PlayerIndex] = 1 then
   if assigned(uosPlayers[PlayerIndex]) then
   begin
uosPlayers[PlayerIndex].Stop();
{$IF DEFINED(mse)}
  freeandnil(uosPlayers[PlayerIndex]);
  uosPlayersStat[PlayerIndex] := -1 ;
{$endif}
end;
end;


I replaced the uos.pas with the new one (though it's not apparently used in my project).
Nothing changed, most sounds stay in ALSA.


I also try to use EndProc but it wouldn't let me use this syntax :

When playing a sound :
uos_Play(nPlayer);
uos_EndProc(nPlayer, @StopSon(nPlayer, nLine));


for launching this procedure :
Procedure StopSon(nPlayer: integer; nLigne: integer);
begin
    uos_stop(nPlayer);
    Form1.GridProg.cells[6, nLigne]:= '';
end;  


Reply | Threaded
Open this post in threaded view
|

Re: How to free the players for real ?

fredvs
Administrator
Hello.

Please download the entire uos project:

Go to https://github.com/fredvs/uos/ and click on the green button "Clone or Download" ---> Download Zip.

Unzip it and use that source.

With Lazarus, do "Open-project" and select/ uos/examples/MorseTL.lpi

Fre;D

 
Reply | Threaded
Open this post in threaded view
|

Re: How to free the players for real ?

fredvs
Administrator
In reply to this post by jeremzw

> uos_flat vs uos.pas: What's the difference between both ?

uos_flat.pas is a over-layer of uos.pas.

Please use uos_flat.pas for your project.

Here wiki of uos.
http://wiki.freepascal.org/uos

Fre;D
Reply | Threaded
Open this post in threaded view
|

Re: How to free the players for real ?

jeremzw
Thanks, understood for uos_flat now, and Morse did work for me.

Sorry though, but I still haven't fixed my problem.

One thought : Maybe I'm creating too many players ?
3 sounds are loaded in advance because I need them to play right away when one is about to finish (to create a mix).

So I'm supposing that it just creates new players without killing the old ones, ever.

I'm willing to use uos_EndProc but it doesn't work.

Since I have several players (sometimes 2 playing at the same time), I need to specify which one I want to stop :

uos_EndProc(Index, @StopSon(Index));

Procedure StopSon(Index: integer);
begin
uos_stop(Index);
...
end;

But it only accepts this syntax :
uos_EndProc(Index, @StopSon);
Reply | Threaded
Open this post in threaded view
|

Re: How to free the players for real ?

fredvs
Administrator
Hello.

I am sorry but I cannot help you at this stage.
We have programs that use 32 players with each 256 inputs and work on little netbooks.

Maybe if you give all your code?

Fre;D
Reply | Threaded
Open this post in threaded view
|

Re: How to free the players for real ?

jeremzw
I believe you, that's why it's so frustrating.

No problem for giving all the code, I should probably upload it on github ?
Reply | Threaded
Open this post in threaded view
|

Re: How to free the players for real ?

fredvs
Administrator
Hello.

You may add as zip attachment here in forum site, click [Reply], then: [More]  + Upload a file.

Fre;D
Reply | Threaded
Open this post in threaded view
|

Re: How to free the players for real ?

jeremzw
I just saw it !

But it's also on github now:
https://github.com/jeangirafe/boite-a-musique

The main player is in unit1.

It basically works like this :
when the button play is hit, it searches in the database for 3 songs, loads all of them in a player, and starts to play the first one.
Then a timer1 is started to control when the program should start the 2nd song and fade the first one and load a new one at the end of the playlist...
Reply | Threaded
Open this post in threaded view
|

Re: How to free the players for real ?

fredvs
Administrator
Hello.

It cannot work!

Please copy **ALL** the sources that are in /uos/src/ into the same directory as your project (not only uos_flat.pas).

Good luck.

Fre;D
Reply | Threaded
Open this post in threaded view
|

Re: How to free the players for real ?

jeremzw
Alright, I just did this. Let's see if it works better.
Reply | Threaded
Open this post in threaded view
|

Re: How to free the players for real ?

fredvs
Administrator
Hello.

I did a fast look to your code:

EndProc is a procedure of Object.

It must be something like this (no argument):

procedure TForm1.MyEndProc();
begin
// add something
end;

Fre;D

Reply | Threaded
Open this post in threaded view
|

Re: How to free the players for real ?

jeremzw
Sorry, I may seem a bit new to all this.
I'm a bit confused now.

I thought uos_EndProc was a procedure from uos, called when a sound was reaching its end in a player.
How can it be a procedure of my Form1 now ?
123