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. :wink: 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