Part of my code goes like this:
while(1){
my $winmm = new Win32::MediaPlayer;
$winmm->load('1.mp3'); $winmm->play; $winmm->volume(100);
Do Some Stuff;
last if some condition is met;
}
Problem is: I want the music to be always on when I'm in the Do Some Stuff stage in the while loop. But the length of the music is so short that it will come to a full stop before I go to the next stage, so I want the music to repeat itself, but the Win32::Mediaplayer module does not seem to have a repeat mode, so I'm thinking of doing an infinite loop for the music playing part. Like this:
while(1){
my $winmm = new Win32::MediaPlayer;
$winmm->load('1.mp3'); $winmm->play; $winmm->volume(100);
}
while(2){
Do some stuff;
last if some condition is met
}
But based on my current Perl knowledge if I'm in the while(1) part, I can never go to the while(2) part. Even if it comes to a nested loop, I have to do something to break out of the inside loop before going to the other part of the outside loop.
The answer to my question "Can we run two simultaneous non-nested loops in Perl?" may be a NO, but I assume there is some way of handling such situation. Correct me if I'm wrong.
Thanks as always for any comments/suggestions :)
UPDATE
I really appreciate the help from everyone. Thanks :) So the answer to my question is a YES, not a NO. I'm happy that I've learned how to use fork() and threads to solve a real problem :)
You can run the two different processes in separate threads.
Something along the lines of:
use strict;
use warnings;
use threads;
use threads::shared;
use Win32::MediaPlayer;
my $killAudio :shared = undef;
my $audio = threads->create(\&playAudio);
my $condition = threads->create(\&doSomething,$audio);
$condition->join();
sub playAudio {
my $winmm = new Win32::MediaPlayer;
$winmm->load('1.mp3') or die 'Could not load file: $!';
$winmm->volume(100);
$winmm->play until $killAudio;
}
sub doSomething {
my $thread = shift;
my $conditionMet = undef;
while (1) {
($conditionMet,$killAudio) = doSomeStuff(); # set doSomeStuff() to
# return only when
# conditions are met
$thread->join() if $killAudio; # This line will terminate $audio
last if $conditionMet;
}
}
UPDATE
Based on Mike's comment below, the playAudio()
subroutine can be rewritten as:
sub playAudio {
my $winmm = new Win32::MediaPlayer;
$winmm->load('1.mp3') or die 'Could not load file: $!';
while (1) {
$winmm->play;
$winmm->volume(100);
sleep($winmm->length/1000);
last if $killAudio;
}
}
You may try to fork, like this:
So you will create 2 threads, one of which will play your music and second one will do all your other stuff.
You should also think on terminating your music thread by some condition
my @child_pids = ();
my $pid = fork();
if ($pid)
{
# parent
push(@child_pids, $pid);
Do some stuff;
last if some condition is met
}
elsif ($pid == 0)
{
# child
while(1){
my $winmm = new Win32::MediaPlayer;
$winmm->load('1.mp3'); $winmm->play; $winmm->volume(100);
}
exit(0);
}
else
{
die "couldn’t fork: $!\n";
}
If your doSomething()
stage fits naturally within a looping structure, you can simply check the status of the song periodically and seek
back to the beginning if the song has ended -- admittedly a hack, but easy.
use strict;
use warnings;
use Win32::MediaPlayer;
my $winmm = Win32::MediaPlayer->new;
$winmm->load($ARGV[0]) or die $!;
$winmm->play;
my $end_of_song = $winmm->length;
# doSomething
for (1 .. 1000){
# Perform difficult computations...
sleep 2;
# Has song ended?
$winmm->seek(0) if $winmm->pos >= $end_of_song;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With