Page 1 of 1
Movie functions don't work in threads
Posted: Fri Mar 11, 2011 11:01 am
by c4s
Code: Select all
Global MovieName$
Procedure Thread(Void)
If LoadMovie(0, MovieName$)
OpenWindow(0, 100, 150, MovieWidth(0), MovieHeight(0), "PureBasic - Movie") ; "Movie not initialized"... although loading doesn't fail
PlayMovie(0, WindowID(0))
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
Else
MessageRequester("Error", "Can't load the movie...", 0)
EndIf
EndProcedure
If InitMovie() = 0
MessageRequester("Error", "Can't initialize movie playback !", 0)
End
EndIf
MovieName$ = OpenFileRequester("Choose the movie to play", "", "Movie/Audio files|*.avi;*.mpg;*.asf;*.mp3;*.wav|All Files|*.*", 0)
If MovieName$
;- Works:
; If LoadMovie(0, MovieName$)
;
; OpenWindow(0, 100, 150, MovieWidth(0), MovieHeight(0), "PureBasic - Movie")
; PlayMovie(0, WindowID(0))
;
; Repeat
; Until WaitWindowEvent() = #PB_Event_CloseWindow
; Else
; MessageRequester("Error", "Can't load the movie...", 0)
; EndIf
;- Doesn't work:
Thread = CreateThread(@Thread(), 0)
WaitThread(Thread)
EndIf
LoadMovie() perfectly works in the thread (as it doesn't return 0) but all following functions seem to fail. The help file says:
Help: LoadMovie() wrote:If the Result is 0, the movie can't be opened (format not supported or file not found), otherwise its ok. PlayMovie() can be used to start playing it.
...so I don't see where the problem is.
Re: Movie functions don't work in threads
Posted: Fri Mar 11, 2011 12:32 pm
by RASHAD
@c4s Hi
InitMovie() must be inside the thread (I think that is logic)
Code: Select all
Global MovieName$
Procedure Thread(Void)
If InitMovie() = 0
MessageRequester("Error", "Can't initialize movie playback !", 0)
End
EndIf
If LoadMovie(0, MovieName$)
OpenWindow(0, 100, 150, MovieWidth(0), MovieHeight(0), "PureBasic - Movie") ; "Movie not initialized"... although loading doesn't fail
PlayMovie(0, WindowID(0))
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
Else
MessageRequester("Error", "Can't load the movie...", 0)
EndIf
EndProcedure
; If InitMovie() = 0
; MessageRequester("Error", "Can't initialize movie playback !", 0)
; End
; EndIf
MovieName$ = OpenFileRequester("Choose the movie to play", "", "Movie/Audio files|*.avi;*.mpg;*.asf;*.mp3;*.wav|All Files|*.*", 0)
;If MovieName$
;- Works:
;LoadMovie(0, MovieName$)
;
; OpenWindow(0, 100, 150, MovieWidth(0), MovieHeight(0), "PureBasic - Movie")
; PlayMovie(0, WindowID(0))
;
; Repeat
; Until WaitWindowEvent() = #PB_Event_CloseWindow
; Else
; MessageRequester("Error", "Can't load the movie...", 0)
; EndIf
;- Doesn't work:
Thread = CreateThread(@Thread(), 0)
WaitThread(Thread)
;EndIf
Re: Movie functions don't work in threads
Posted: Fri Mar 11, 2011 12:50 pm
by c4s
Wow Rashad, that's an interesting solution. Thank you!
I thought InitXXX() is something similar to UseXXXEncoder(). I mean that I have to call it just once at the beginning of my code... Does it mean I can only use this specific thread for the movie commands then?
Well, I could live with that for my current project as it's better then not being able to do so, but of course using them everywhere would be better. Also the help file really needs a note on this!
Edit:
Oh, not good when I want to use the thread multiple times and I think using it simultaneously doesn't work either.

Re: Movie functions don't work in threads
Posted: Fri Mar 11, 2011 1:30 pm
by RASHAD
Give us some code mate
Tested with PB 4.51 x86 Win 7 x64
Code: Select all
Global MovieName$,Thread,Run
Procedure Thread(parameter)
If Run = 0
InitMovie()
InitSound()
EndIf
Run = 1
LoadMovie(parameter, MovieName$)
OpenWindow(0, 100, 150, MovieWidth(parameter), MovieHeight(parameter), "PureBasic - Movie") ; "Movie not initialized"... although loading doesn't fail
PlayMovie(parameter, WindowID(0))
Delay(20000)
StopMovie(parameter)
FreeMovie(parameter)
CloseWindow(0)
EndProcedure
MovieName$ = OpenFileRequester("Choose the movie to play", "", "Movie/Audio files|*.avi;*.mp4;*.asf;*.mp3;*.wav|All Files|*.*", 0)
Thread = CreateThread(@Thread(), 0)
WaitThread(Thread)
If IsThread(Thread) = 0
MovieName$ = OpenFileRequester("Choose the movie to play", "", "Movie/Audio files|*.avi;*.mp4;*.asf;*.mp3;*.wav|All Files|*.*", 0)
Thread = CreateThread(@Thread(), 1)
WaitThread(Thread)
EndIf
Re: Movie functions don't work in threads
Posted: Fri Mar 11, 2011 2:31 pm
by Trond
The movie library uses DirectX and DirectX can't be used in threads (Windows limitation), so it's not surprising that it doesn't work.
Re: Movie functions don't work in threads
Posted: Fri Mar 11, 2011 2:59 pm
by c4s
Wait Trond, this seems to work here (on XP):
Code: Select all
EnableExplicit
Global MovieName$, MovieInitialized, ThreadNr
Procedure Thread(Void)
;If MovieInitialized = #False
InitMovie() ; Ignoring the Debugger Error here seems to work
MovieInitialized = #True
;EndIf
If LoadMovie(0, MovieName$)
If OpenWindow(1, 0, 0, 0, 0, "Movie", #PB_Window_Invisible)
PlayMovie(0, WindowID(1))
Repeat : Delay(50) : Until MovieStatus(0) < 1
CloseWindow(1) ; Close when movie has stopped
EndIf
FreeMovie(0)
EndIf
EndProcedure
MovieName$ = OpenFileRequester("Choose the movie to play hidden", "", "Movie/Audio files|*.avi;*.mpg;*.asf;*.mp3;*.wav|All Files|*.*", 0)
If Len(MovieName$) > 0
Debug "First time"
ThreadNr = CreateThread(@Thread(), 0)
WaitThread(ThreadNr)
Debug "Second time"
ThreadNr = CreateThread(@Thread(), 0)
WaitThread(ThreadNr)
EndIf
Well, at least I expect that this is clearly stated in the help file. It already took me a while to find out that the movie commands don't work in threads...
Re: Movie functions don't work in threads
Posted: Fri Mar 11, 2011 3:03 pm
by RASHAD
Re: Movie functions don't work in threads
Posted: Fri Mar 11, 2011 9:53 pm
by c4s
Since I just want to play some audio files like mp3 etc. MCI works just fine, so I'm going to use this instead of the Movie functions:
Code: Select all
EnableExplicit
Global MovieName$, ThreadNr
Macro MCIID(Nr)
"sound" + Str(Nr)
EndMacro
Macro MCIFree(Nr)
mciSendString_("close " + MCIID(Nr), 0, 0, 0)
EndMacro
Macro MCILoad(Nr, Filename)
mciSendString_("open " + #DQUOTE$ + Filename + #DQUOTE$ + " type mpegvideo alias " + MCIID(Nr), 0, 0, 0)
EndMacro
Macro MCIPlay(Nr)
mciSendString_("play " + MCIID(Nr), 0, 0, 0)
EndMacro
Procedure MCILength(Nr)
Protected Length.s = Space(#MAX_PATH)
mciSendString_("status " + MCIID(Nr) + " length", @Length, #MAX_PATH, 0)
ProcedureReturn Val(Length)
EndProcedure
Procedure MCIPosition(Nr)
Protected Position.s = Space(#MAX_PATH)
mciSendString_("status " + MCIID(Nr) + " position", @Position, #MAX_PATH, 0)
ProcedureReturn Val(Position)
EndProcedure
Procedure Thread(Void)
If MCILoad(0, MovieName$) = 0 ; 0=Success
MCIPlay(0)
While MCIPosition(0) < MCILength(0) : Delay(50) : Wend
EndIf
MCIFree(0)
EndProcedure
MovieName$ = OpenFileRequester("Choose the movie to play hidden", "", "Movie/Audio files|*.avi;*.mpg;*.asf;*.mp3;*.wav|All Files|*.*", 0)
If Len(MovieName$) > 0
Debug "First time"
ThreadNr = CreateThread(@Thread(), 0)
WaitThread(ThreadNr)
Debug "Second time"
ThreadNr = CreateThread(@Thread(), 0)
WaitThread(ThreadNr)
EndIf
...But my original post is still valid: The help file doesn't say that the movie commands don't work in threads and the compiler isn't very helpful here either.
Re: Movie functions don't work in threads
Posted: Tue Oct 25, 2011 9:43 am
by c4s
I'm thinking about replacing the MCI code by the PureBasic Movie functions, being inspired by this thread
http://www.purebasic.fr/english/viewtop ... 13&t=47977
I already forgot why I didn't start to use them initially more than a half year ago... Anyway, this (my own) thread is the answer to that question: I didn't use them because they don't really seem to work in a seperate thread. Is there anything more reliable than this?
Code: Select all
EnableExplicit
Global MovieName$, MovieInitialized, ThreadNr
Procedure Thread(Void)
;If MovieInitialized = #False
InitMovie() ; Ignoring the Debugger Error here seems to work
MovieInitialized = #True
;EndIf
If LoadMovie(0, MovieName$)
If OpenWindow(1, 0, 0, 0, 0, "Movie", #PB_Window_Invisible)
Debug PlayMovie(0, WindowID(1))
Repeat : Delay(50) : Until MovieStatus(0) < 1
CloseWindow(1) ; Close when movie has stopped
EndIf
FreeMovie(0)
EndIf
EndProcedure
MovieName$ = OpenFileRequester("Choose the movie to play hidden", "", "Movie/Audio files|*.avi;*.mpg;*.asf;*.mp3;*.wav|All Files|*.*", 0)
If Len(MovieName$) > 0
Debug "First time"
ThreadNr = CreateThread(@Thread(), 0)
WaitThread(ThreadNr)
Debug "Second time"
ThreadNr = CreateThread(@Thread(), 0)
WaitThread(ThreadNr)
EndIf
I simply need to play MP3 files and the like in a thread without having to use MCI anymore, nor an external sound library (bass dll etc.)... Any ideas?
Re: Movie functions don't work in threads
Posted: Tue Oct 25, 2011 3:45 pm
by michaeled314
I would like to thank everybody on these MCI threads for supporting me and helping me through this obstacle.... I am now opening the MCI file in a thread and everything is working fine... Before I run the thread I will use the MCI test flag to see if it is the correct file format for MCI... I will be in deep !@#$ if Microsoft ever discontinues MCI though, since the PB movie library is not quite as powerful... I guess it will come down to interpreting raw WAVE block data

never ever want to take that much pain to learn to do that.

Re: Movie functions don't work in threads
Posted: Tue Oct 25, 2011 5:23 pm
by Shield
Trond wrote:The movie library uses DirectX and DirectX can't be used in threads (Windows limitation), so it's not surprising that it doesn't work.
That's nonsense.

Yeah, I know it's written that way in the help file and hasn't be changed for years, but that doesn't make it right.
DirectX can very well be used within threads, as long as calls don't get mixed up between different threads.
Re: Movie functions don't work in threads
Posted: Wed Oct 26, 2011 3:37 pm
by michaeled314
Handy little MCI Callback Function
Code: Select all
Structure MCIOpenParams
FileName.s
Alias.s
EndStructure
Global MCIMsg.l = 0
Procedure.l MCIOpen(Alias.s, FileName.s)
Error = mciSendString_("open "+Chr(34)+FileName+Chr(34)+" type mpegvideo alias "+Alias,0,0,0)
ProcedureReturn Error
EndProcedure
Procedure.l MCIPlay(Alias.s, FromPos.l, ToPos.l)
mciString.s = "play "+Alias
If FromPos
mciString + " from "+Str(FromPos)
If ToPos
mciString + " to "+Str(ToPos)
EndIf
EndIf
Error = mciSendString_(mciString,0,0,0)
ProcedureReturn Error
EndProcedure
Procedure MCICallbackThread(*p.MCIOpenParams)
Repeat
;process your messages here
Until MCIMsg = #MCI_CLOSE
EndProcedure
*open.MCIOpenParams = AllocateMemory(SizeOf(MCIOpenParams))
*open\FileName = OpenFileRequester("","","*.*",0)
*open\Alias = "1"
CreateThread(@MCICallbackThread(),*open)
OpenConsole()
Repeat
Until GetAsyncKeyState_(#VK_ESCAPE)
MCIMsg = #MCI_CLOSE