Load sound from TMemoryStream

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

Re: Load sound from TMemoryStream

Phoenix
Hello,
I wanted to know how something works:

Both solutions for Tuos_Player.FreePlayer ();
they make sure that the thread is Free
(Given the presence of "FreeOnTerminate: = True;")

If you are using Tuos_Player.FreePlayer (); separately before uos_Free ():
uosPlayers [] is updated to nil?
(I tested it and it seems to me no)

Because the uos_Free call ()

for x: = 0 to length (uosPlayers) -1 do
   begin
   if assigned (uosPlayers [x]) then  <WARNING>
   begin
    uosPlayers [x] .FreePlayer;
   end;

It risks a problem

I saw Tuos_Player.onTerminate ();
but it does not run!

procedure Tuos_Player.onTerminate() ;
begin
if ifflat = true then
  begin
  uosPlayers[Index].destroy;
uosPlayersStat[Index] := -1 ;
end else destroy;
end;

and it is not correct (the free thread is automatic)

http://lazarus-ccr.sourceforge.net/docs/rtl/classes/tthread.doterminate.html

or

http://lazarus-ccr.sourceforge.net/docs/rtl/classes/tthread.onterminate.html

procedure Tuos_Player.;
begin
 uosPlayers[Index]:= nil;
 uosPlayersStat[Index] := -1 ;
end;
Reply | Threaded
Open this post in threaded view
|

Re: Load sound from TMemoryStream

fredvs
Administrator
Hello.

Thanks to note it.

Indeed, few time ago (because of LCL that does not free everything if FreeOnTerminate: = false, even after player.free), I added  FreeOnTerminate: = true (and that way, all is freed in LCL too).

Write you later.

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

Re: Load sound from TMemoryStream

Phoenix
Hello,
sorry if I add other things but I think they should be seen together..

I made a remark perhaps interesting.
In "uos_Free ()" method there is "Sleep (50)".
If I use "uos_Free ()" instead of "freeplayer" the value 50 is not enough and then crash (not for a real problem), but if I put for example Sleep(1000) then it works (for my computer).
Probably even my crash and caused a few problems in the timings (Play (), Stop () solution).
I think there are values of sleep that some computers are not for others. I think it would be useful to have a method that makes the sleep function but also that controls the actual execution.

while ..control.. do
 Sleep(10);

for example:
(tested with the changes introduced in previous post)

function ThereArePlayersNotFree: Boolean;
Var
 i: Integer;
begin
 if uosPlayers <> nil then
  for i:= 0 to Length(uosPlayers)-1 do
   if uosPlayersStat[i] <> -1 then
   begin
    Result:= True;
    Exit;
   end;
 Result:= False;
end;

procedure uos_Free();
...

//sleep(50); old code

while ThereArePlayersNotFree do
 Sleep(10);
...
end;

so in theory make code more robust (it does not think the appropriate value sleep).

This should also be applied to other situations for the use of Sleep.

PS.
I do not currently know if it also requires the use of a TCriticalSection.
I just made a simple test with a single player and it works.
But the basic idea I think would be interesting to apply.

Note:
I believe that the following line will be adjusted:
if uosPlayers[PlayerIndex] <> nil then uosPlayers[PlayerIndex].Terminate;
(procedure uos_CreatePlayer(PlayerIndex : cint32);)
with the execute() current has no effect
Reply | Threaded
Open this post in threaded view
|

Re: Load sound from TMemoryStream

fredvs
Administrator
This post was updated on .
Hello.

Ok, change commited in 8d9c856..65065e9, I hope it is better now.:

Procedure uos_FreePlayer(PlayerIndex: cint32) ;  // Works only when PlayNoFree() was used: free the player
begin
  if (length(uosPlayers) > 0) and (PlayerIndex +1 <= length(uosPlayers)) then
  if  uosPlayersStat[PlayerIndex] = 1 then
begin
uosPlayers[PlayerIndex].FreePlayer() ;
uosPlayers[PlayerIndex] := nil;
end
end;

PS: I did not study yet your last topic, maybe the new release solve the problems.

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

Re: Load sound from TMemoryStream

fredvs
Administrator
This post was updated on .
Re-hello.

Ooops, Player.OnTerminate() ---> was not used ---> old code from 5 years ago ;-(

Removed in last commit 65065e9..ffeee3b.

I will study your last topic asap.

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

Re: Load sound from TMemoryStream

fredvs
Administrator
Re-re-hello.

Re-added with correct parameter Player.OnTerminate(sender: Tobject).
---> (sender: Tobject) was missing in old releases --> added:

procedure Tuos_Player.OnTerminate(sender : Tobject);
begin
inherited OnTerminate(sender);
if ifflat = true then
  begin
  uosPlayers[Index] := nil;
  uosPlayersStat[Index] := -1 ;
 end;
end;

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

Re: Load sound from TMemoryStream

Phoenix
Hello,

there is a programming problem

procedure OnTerminate(sender: Tobject);  

procedure Tuos_Player.OnTerminate(sender : Tobject);
begin
inherited OnTerminate(sender);//???
if ifflat = true then
  begin
  uosPlayers[Index] := nil;
  uosPlayersStat[Index] := -1 ;
 end;
end;

WHERE IS USED IT?
NOT WORK!
(If you want to check, for example, you write an empty file with OnTerminate: you will see that is not called)

you can use:

virtual method of TThread

procedure DoTerminate; override;

or

assign event for TThread

OnTerminate:= OnTerminateEvent;

To my problem see previous post about "Sleep (50)"

PS.
for the alternative solution post "Mar 17, 2017; 7:39pm" What do you think?
Reply | Threaded
Open this post in threaded view
|

Re: Load sound from TMemoryStream

fredvs
Administrator
Hello.

OK, I have added your proposition, many thanks : Commit 69416bb..acf9b78

function PlayersNotFree: Boolean;
Var
 i: Integer;
begin
 if uosPlayers <> nil then
  for i:= 0 to Length(uosPlayers)-1 do
     if uosPlayers[i] <> nil then
   begin
    Result:= True;
    Exit;
   end;
 Result:= False;
end;

procedure uos_Free();
var
x : integer;
begin

if assigned(uosPlayers) then
if length(uosPlayers) > 0 then
 for x := 0 to length(uosPlayers) -1 do
  begin
  if assigned(uosPlayers[x]) then
  begin
   uos_FreePlayer(x);
  end;
  end;

while PlayersNotFree do Sleep(10);  
 
uos.uos_free();
end;

procedure uos_unloadlib() ;
  var
  x: cint32;
  begin
  if assigned(uosPlayers) then
  begin
  if (length(uosPlayers) > 0) then
  for x := 0 to high(uosPlayers) do
  if  uosPlayersStat[x] = 1 then
  begin
  if  uosPlayers[x].Status > 0 then
  begin
  uosPlayers[x].nofree := false;
  uosPlayers[x].Stop();
  while PlayersNotFree do Sleep(10);
  end;
  end;

  setlength(uosPlayers, 0) ;
  setlength(uosPlayersStat, 0) ;
  end;

 uos.uos_unloadlib() ;
end;

PS: All sleep are using your method in uos_flat.pas

For uos.pas, the conditions are different, each case must have his own sleep-method.
It is on the todo list.

Many thanks.

-----------------------------

From your last topic:

> WHERE IS USED IT? NOT WORK!

Hah, strange, here it works, did you try last commit ?

> for the alternative solution post "Mar 17, 2017; 7:39pm" What do you think?

Is not what I did in last commits ?


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

Re: Load sound from TMemoryStream

fredvs
Administrator
This post was updated on .
In reply to this post by Phoenix
Hello.

> NOT WORK!

OK, I am lost.

I ask help in fpc forum.

http://free-pascal-general.1045716.n5.nabble.com/TThread-OnTerminate-td5727888.html#a5727910

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

Re: Load sound from TMemoryStream

Phoenix
Hello,

Thank you for your changes,
then I write to you for a few details..

> OK, I am loosed.
> I ask help in fpc forum.

Because?
if you've chosen to use the virtual method

CERTAIN THAT DOES NOT WORK
procedure OnTerminate(sender: Tobject); override;

it may be that you have not seen the "DOterminate" in my post: "DO..." not "ON..."

for solve

procedure DOTerminate; override;
Reply | Threaded
Open this post in threaded view
|

Re: Load sound from TMemoryStream

fredvs
Administrator
Hello.

OK, finally, I get it.
Added Tuos_Player.DoTerminate in last commit acf9b78..69db11a.

Many thanks for help Phoenix.

PS: Do you have still problems with last release ?

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

Re: Load sound from TMemoryStream

fredvs
Administrator
Re-hello.

Hum, I realize that maybe in Tuos_Player.DoTerminate;

---> inherited DoTerminate;

is not needed.

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

Re: Load sound from TMemoryStream

Phoenix
Hello,
Thank you for your changes.

> inherited DoTerminate;

in this case I think if leave it or remove it does not change

> Do you have still problems with last release ?

Yes, DoTerminate work but I have a crash because there is one detail

There is an issue to use properly PlayersNotFree ().
In my solution use:
"If uosPlayersStat [i] <> -1 then"

sorry for (error in my post)
"if uosPlayers <> nil then
 for i:= 0 to Length(uosPlayers)-1 do"

function PlayersNotFree: Boolean;
Var
 i: Integer;
begin
 if uosPlayersStat <> nil then
  for i:= 0 to Length(uosPlayersStat)-1 do
   if uosPlayersStat[i] <> -1 then
   begin
    Result:= True;
    Exit;
   end;
 Result:= False;
end;

But even this (yours) can work:

"If uosPlayers [i] <> nil then"

the problem is in:

Procedure uos_FreePlayer(PlayerIndex: cint32) ;
begin
  ............
  uosPlayers[PlayerIndex].FreePlayer() ;
  uosPlayers[PlayerIndex] := nil; <<< THIS
  uosPlayersStat[PlayerIndex] := -1; <<< THIS
 end
end;

these lines are to be performed in DoTerminate (after the actual execution of freeplayer ()) or the "while" blocks at the first sleep (10)

if you want to leave at least "uosPlayers [PlayerIndex]: = nil;" you have to use PlayersNotFree () with "uosPlayersStat"

NOTE:
consider that you may run into an infinite loop potential if for example a thread does not end.
This is easily avoidable but bypassing the "while", if a thread is not terminated, however you would get an access to invalid memory or a visible crash (my case).

> For uos.pas, the conditions are different, each case must have his own sleep-method.
It is on the todo list

I am glad that you have found interesting the idea.
The solution should be used where it is really needed in order to avoid infinite loops (on the thread are also more dangerous).
So you have to be very careful.
Where it is needed more attention you can put in check some sort of time limit (certainly avoid the infinite loop).

Only for example

 nt:= 300; //= 3 second (big enough to cover every possibility of the case)
 while ..control.. and (nt <> 0) do
 begin
  Sleep(10);
  Dec(nt);
 end;

sorry for my English (with all these posts there will be a lot of mistakes)

 Thanks
Reply | Threaded
Open this post in threaded view
|

Re: Load sound from TMemoryStream

Phoenix
Hello,
sorry I just posted (watch it) but there is a consideration

uosPlayers [PlayerIndex]: = nil; need in uos_FreePlayer ()
because need in uos_Free()

then you can only use "uosPlayersStat" solution for PlayersNotFree() and remove only "uosPlayersStat[PlayerIndex] := -1;" from uos_FreePlayer()

(read the previous post)
Reply | Threaded
Open this post in threaded view
|

Re: Load sound from TMemoryStream

fredvs
Administrator
Hello Phoenix.

Thanks for your light.
It is very useful because ... with my computer (netbook Lenovo) I do not have any crash.

Is this code OK ? :

function PlayersNotFree: Boolean;
Var
 i: Integer;
begin
 if uosPlayersStat <> nil then
  for i:= 0 to Length(uosPlayersStat)-1 do
   if uosPlayersStat[i] <> -1 then
   begin
    Result:= True;
    Exit;
   end;
 Result:= False;
end;

Procedure uos_FreePlayer(PlayerIndex: cint32) ;  
begin
  if (length(uosPlayers) > 0) and (PlayerIndex +1 <= length(uosPlayers)) then
  if  uosPlayersStat[PlayerIndex] = 1 then
begin
uosPlayers[PlayerIndex].FreePlayer() ;
uosPlayers[PlayerIndex] := nil;
end;
end;

procedure uos_Free();
var
x : integer;
nt : integer = 300;
begin

if assigned(uosPlayers) then
if length(uosPlayers) > 0 then
 for x := 0 to length(uosPlayers) -1 do
  begin
  if assigned(uosPlayers[x]) then
  begin
   uos_FreePlayer(x);
  end;
  end;

while (PlayersNotFree = true) and (nt > 0) do
 begin
  Sleep(10);
  Dec(nt);
 end;
 
uos.uos_free();
end;

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

Re: Load sound from TMemoryStream

fredvs
Administrator
Re-hello.

Change from previous post are in last commit 69db11a..5fc2425.

I hope this one is the good one ;-)
(If no, no problem, we will win at the end).

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

Re: Load sound from TMemoryStream

Phoenix
Hello,
I tested with several combinations is that everything seems to work perfect !!

PS.
the only thing in common with the two computers I used for the test are the number of cores, and Windows:
1) intel four cores (more than 5 years of age) Win Vista 32bit
2) intel four cores (8 threads) Win 10 64bit
On the second computer with linux, no crash with (Sleep(50))

 Thanks!!
Reply | Threaded
Open this post in threaded view
|

Re: Load sound from TMemoryStream

fredvs
Administrator
Yep, many thanks for your help.

Fred.
1234