Movie functions don't work in threads

Just starting out? Need help? Post your questions and find answers here.
c4s
Addict
Addict
Posts: 1981
Joined: Thu Nov 01, 2007 5:37 pm
Location: Germany

Movie functions don't work in threads

Post 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.
If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: Movie functions don't work in threads

Post 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

Egypt my love
c4s
Addict
Addict
Posts: 1981
Joined: Thu Nov 01, 2007 5:37 pm
Location: Germany

Re: Movie functions don't work in threads

Post 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. :(
If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: Movie functions don't work in threads

Post 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
Egypt my love
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Re: Movie functions don't work in threads

Post 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.
c4s
Addict
Addict
Posts: 1981
Joined: Thu Nov 01, 2007 5:37 pm
Location: Germany

Re: Movie functions don't work in threads

Post 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...
If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: Movie functions don't work in threads

Post by RASHAD »

Egypt my love
c4s
Addict
Addict
Posts: 1981
Joined: Thu Nov 01, 2007 5:37 pm
Location: Germany

Re: Movie functions don't work in threads

Post 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.
If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
c4s
Addict
Addict
Posts: 1981
Joined: Thu Nov 01, 2007 5:37 pm
Location: Germany

Re: Movie functions don't work in threads

Post 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?
If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
michaeled314
Enthusiast
Enthusiast
Posts: 340
Joined: Tue Apr 24, 2007 11:14 pm

Re: Movie functions don't work in threads

Post 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. ;)
User avatar
Shield
Addict
Addict
Posts: 1021
Joined: Fri Jan 21, 2011 8:25 am
Location: 'stralia!
Contact:

Re: Movie functions don't work in threads

Post 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.
Image
Blog: Why Does It Suck? (http://whydoesitsuck.com/)
"You can disagree with me as much as you want, but during this talk, by definition, anybody who disagrees is stupid and ugly."
- Linus Torvalds
michaeled314
Enthusiast
Enthusiast
Posts: 340
Joined: Tue Apr 24, 2007 11:14 pm

Re: Movie functions don't work in threads

Post 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
Post Reply