Board index » cppbuilder » TMediaPlayer plays a loop

TMediaPlayer plays a loop


2006-07-04 05:24:49 AM
cppbuilder62
First the good news:
There is a main form containing a List Box which displays a list of
music files using TMediaPlayer. The main form also contains needed
buttons to control the media player each with its own code. The player
works properly , playing the music using a loop coded as follows:
void __fastcall TForm1::StartBtnClick(TObject *Sender)
{
int NumLines = MusicList->Items->Count;
// various other declarations
int i = 0;
MusicList->ItemIndex = i;
// loops through the lines in the music file
for(;i < NumLines; i++)
{
// a series of if statements for cut copy and paste operations
MusicProgramLine = MusicList->Iems->Strings[i];
// Method to extract the music file name and path from the music file line
MusicPath = GetMusFilNam(MusicProgramLine);
if(FileExists(MusicPath))
{
MediaPlayer1->FileName = MusicPath;
MediaPlayer1->Open( );
// enable the available buttons which control the Media Player
UpdateControls( );
MediaPlayer1->Wait = false;
MediaPlayer1->Play( );
// set available buttons which may now control the Media Player
UpdateControls( );
while (MediaPlayer1->Mode == mpPlaying)
{
Application->ProcessMessages( );
}
} // end of if (File Exists)
} // end of for ( ) loop
Now for the bad news:
In a related MDI program the Main Form contains several MDI pages which list
music files of various types ... Tango, Mambo, Cha Cha .. etc.
These MDI forms contains a ListBox to display the list. There is also a
button to "Play a Selected Line" and a button to "Play the Entire List".
"Play a Selected Line" plays the selected line properly.
"Play the Entire List" simply loops through the entire list and plays the
last item.
It acts as if the code "Application->ProcessMessages( );" is not doing its
job.
The only way to get the entire list to play is to set
MediaPlayer1->Wait = false; to read MediaPlayer1 ->Wait = true;
which means the MediaPlayer does not return when music is palyed, this
disabling
player controls such as Stop, Pause.. or other buttons.
In stepping through he code, the line "Application->ProcessMessages" appears
to
execute ..... but I think it is not working.
Is there something about MDI forms giving a problem? Some property not set
correctly?
What has been overlooked here?
Happy Dancing! Doug.
 
 

Re:TMediaPlayer plays a loop

"Doug Vanderwater" < XXXX@XXXXX.COM >wrote in message
Quote
There is a main form containing a List Box which displays a list of
music files using TMediaPlayer. The main form also contains needed
buttons to control the media player each with its own code. The player
works properly , playing the music using a loop coded as follows:
I would strongly suggest getting rid of the loop altogether. Use the
OnNotify event instead, ie:
private:
int CurrentLine = -1;
void __fastcall TForm1::PlayNextLine()
{
if( CurrentLine < 0 )
return;
while( CurrentLine < MusicList->Items->Count )
{
MusicProgramLine = MusicList->Items->Strings[CurrentLine++];
MusicPath = GetMusFilNam(MusicProgramLine);
if( FileExists(MusicPath) )
{
MediaPlayer1->FileName = MusicPath;
MediaPlayer1->Wait = false;
MediaPlayer1->OnNotify = MediaPlayer1NotifyOpen;
MediaPlayer1->Open();
return;
}
}
}
void __fastcall TForm1::StartBtnClick(TObject *Sender)
{
CurrentLine = 0;
MusicList->ItemIndex = CurrentLine;
PlayNextLine();
}
void __fastcall TForm1::MediaPlayer1NotifyOpen(TObject *Sender)
{
UpdateControls();
MediaPlayer1->Wait = false;
MediaPlayer1->OnNotify = MediaPlayer1NotifyPlay;
MediaPlayer1->Play();
}
void __fastcall TForm1::MediaPlayer1NotifyPlay(TObject *Sender)
{
UpdateControls();
PlayNextLine();
}
Quote
"Play the Entire List" simply loops through the entire list and plays
the last item. It acts as if the code "Application->ProcessMessages( );"
is not doing its job.
Yes, it is. You are just not using it properly. For starters, since you
have Wait=false, you are not taking into account that the Mode may not be
mpPlaying right away. In fact, Wait is false by default, so when you call
Open(), the Mode has likely not even been set to mpOpen yet when your
ProcessMessages() loop is reached, so your loop exits immediately and moved
on to the next file, canceling the pending file. You really need to use the
Wait property more carefully. Or better, use the OnNotify event, like I
show above.
Gambit
 

Re:TMediaPlayer plays a loop

Hello Gambit:
Thank you for the reply.
The code has been entered into the MDI program and it compiles propely.
Borland Builder Professional Ver 5 is in use.
On executing "Start Button Click" the first item in the music list is
highlighted
but nothing plays.
(Clicking the visible media player button , the first item does play
These buttons are usually hidden in this program)
I am now trying to understand what mechanisms are at work as there may
be an error in my including the recommended code in this program.
In the associated .h file Private:
int CurrentLine; is declared and
its
assignment to -1 is made in .....
:TForm(Owner)
The available Help File for TMediaPlayer Shows "On Notify" as having
two possible assignments .... True and False. In the example code the
assignment is to "MediaPlayer1NotifyOpen" which appears to call a
function/method. I am trying to understand this particular line.
There is a similar line in :: MediaPlayer1NotifyOpen (TObject *Sender)
where "On Notify" is assigned "MediaPlayer1NotifyPlay" which also
appears to call a function/method.
Execution seems to stall at "MediaPlayer1->Open( )" and the next line
"return".
I am in the process of stepping through the code to find out how it is
flowing.
As always, I am dancing as fast as I can! Thanks, Doug.
"Remy Lebeau (TeamB)" < XXXX@XXXXX.COM >wrote in message
Quote

"Doug Vanderwater" < XXXX@XXXXX.COM >wrote in message
news:44a98b22$ XXXX@XXXXX.COM ...

>There is a main form containing a List Box which displays a list of
>music files using TMediaPlayer. The main form also contains needed
>buttons to control the media player each with its own code. The player
>works properly , playing the music using a loop coded as follows:

I would strongly suggest getting rid of the loop altogether. Use the
OnNotify event instead, ie:

private:
int CurrentLine = -1;

void __fastcall TForm1::PlayNextLine()
{
if( CurrentLine < 0 )
return;

while( CurrentLine < MusicList->Items->Count )
{
MusicProgramLine = MusicList->Items->Strings[CurrentLine++];

MusicPath = GetMusFilNam(MusicProgramLine);
if( FileExists(MusicPath) )
{
MediaPlayer1->FileName = MusicPath;
MediaPlayer1->Wait = false;
MediaPlayer1->OnNotify = MediaPlayer1NotifyOpen;
MediaPlayer1->Open();
return;
}
}
}

void __fastcall TForm1::StartBtnClick(TObject *Sender)
{
CurrentLine = 0;
MusicList->ItemIndex = CurrentLine;
PlayNextLine();
}

void __fastcall TForm1::MediaPlayer1NotifyOpen(TObject *Sender)
{
UpdateControls();
MediaPlayer1->Wait = false;
MediaPlayer1->OnNotify = MediaPlayer1NotifyPlay;
MediaPlayer1->Play();
}

void __fastcall TForm1::MediaPlayer1NotifyPlay(TObject *Sender)
{
UpdateControls();
PlayNextLine();
}

>"Play the Entire List" simply loops through the entire list and plays
>the last item. It acts as if the code "Application->ProcessMessages( );"
>is not doing its job.

Yes, it is. You are just not using it properly. For starters, since you
have Wait=false, you are not taking into account that the Mode may not be
mpPlaying right away. In fact, Wait is false by default, so when you call
Open(), the Mode has likely not even been set to mpOpen yet when your
ProcessMessages() loop is reached, so your loop exits immediately and
moved
on to the next file, canceling the pending file. You really need to use
the
Wait property more carefully. Or better, use the OnNotify event, like I
show above.


Gambit


 

{smallsort}

Re:TMediaPlayer plays a loop

"Doug Vanderwater" < XXXX@XXXXX.COM >wrote in message
Quote
On executing "Start Button Click" the first item in the music
list is highlighted but nothing plays.
Did you verify that the file exists? Did you verify that the OnNotify event
handlers are being triggered properly?
Quote
I am now trying to understand what mechanisms are at work as there
may be an error in my including the recommended code in this program.
In a nutshell, the code I gave you is doing the following:
- it maintains a separate variable for the index into the current playing
item in the list
- upon pressing the start button, the index is initialized to the first item
- the OnNotify event handler is set to an event handler for the open
notification, and the current indexed file is opened
- when the media player triggers the event handler indicates that the file
has been opened successfully, it resets the event handler and then plays the
current loaded file
- when the file finishes playing, the index is incremented to the next item
in the list, and the above 2 steps are repeated
One thing I forgot to include is error checking inside the event handlers.
Try this code:
private:
int CurrentLine = -1;
void __fastcall TForm1::PlayNextLine()
{
++CurrentLine;
while( CurrentLine < MusicList->Items->Count )
{
MusicProgramLine = MusicList->Items->Strings[CurrentLine];
MusicPath = GetMusFilNam(MusicProgramLine);
if( !FileExists(MusicPath) )
{
++CurrentLine;
continue;
}
MusicList->ItemIndex = CurrentLine;
MediaPlayer1->FileName = MusicPath;
MediaPlayer1->Wait = false;
MediaPlayer1->OnNotify = MediaPlayer1NotifyOpen;
MediaPlayer1->Open();
return;
}
MusicProgramLine = "";
MusicPath = "";
}
void __fastcall TForm1::StartBtnClick(TObject *Sender)
{
CurrentLine = -1;
PlayNextLine();
}
void __fastcall TForm1::MediaPlayer1NotifyOpen(TObject *Sender)
{
UpdateControls();
if( MediaPlayer1->NotifyValue == nvSuccessful )
{
MediaPlayer1->Wait = false;
MediaPlayer1->OnNotify = MediaPlayer1NotifyPlay;
MediaPlayer1->Play();
}
else
PlayNextLine();
}
void __fastcall TForm1::MediaPlayer1NotifyPlay(TObject *Sender)
{
UpdateControls();
if( MediaPlayer1->NotifyValue == nvSucceessful )
PlayNextLine();
}
Quote
The available Help File for TMediaPlayer Shows "On Notify"
as having two possible assignments .... True and False.
The Notify property is a bool. The OnNotify property is an event.
Quote
In the example code the assignment is to "MediaPlayer1NotifyOpen"
which appears to call a function/method.
It does not call the method. To do that, the method name would have to be
followed by paranthesis. Without the paranthesis, the method's address is
taken instead. In this case, the address of the method itself it being
assigned to the event as its handler. The method is not called until the
event is triggered later on.
Quote
There is a similar line in :: MediaPlayer1NotifyOpen (TObject *Sender)
where "On Notify" is assigned "MediaPlayer1NotifyPlay" which also
appears to call a function/method.
Same as above.
Gambit
 

Re:TMediaPlayer plays a loop

Hello Gambit:
Thank you! The code does execute as expected.
Quote
Did you verify that the OnNotify event
handlers are being triggered properly?
As you suspected, the event handlers were not being triggered properly.
In the function :: PlayNextLine( )
adding the line
MediaPlayer1->Notify = true;
following the line
MediaPlayer1->Wait = false;
started the process moving.
There is more here for me to do in finishing up this program, but everything
should be ok. Thanks for your insight into how the MediaPlayer works,
there is a lot here for me to learn ....
I am hoping some day to include a VU Meter in the program, something that
has escaped me for several years and seems beyond my scope just now ..
Still Dancing .. Doug.