1 // -------------------------------------------------------------------------
4 // Author: Guilhem Lavaux
7 // Copyright: (C) 1997, 1998, 1999 Guilhem Lavaux
8 // License: wxWindows license
9 // -------------------------------------------------------------------------
11 #include "wx/wxprec.h"
19 #include "wx/gtk/win_gtk.h"
23 #include <X11/Intrinsic.h>
25 #include <gtk/gtkwidget.h>
26 #include <gtk/gtkwindow.h>
28 #include <gdk/gdkprivate.h>
31 #include "wx/filefn.h"
32 #include "wx/wfstream.h"
33 #include "wx/datstrm.h"
34 #include "wx/tokenzr.h"
36 #define WXMMEDIA_INTERNAL
37 #include "wx/mmedia/vidbase.h"
38 #include "wx/mmedia/vidxanm.h"
40 IMPLEMENT_DYNAMIC_CLASS(wxVideoXANIM
, wxVideoBaseDriver
)
42 // -------------------------------------------------------------------------
43 // End process detector
45 class wxVideoXANIMProcess
: public wxProcess
{
47 wxVideoXANIMProcess(wxVideoXANIM
*xanim
);
49 void OnTerminate(int pid
, int status
);
52 wxVideoXANIM
*m_vid_xanim
;
55 class wxVideoXANIMOutput
: public wxProcess
{
59 void OnTerminate(int pid
, int status
);
61 bool IsTerminated() const;
66 // -------------------------------------------------------------------------
67 // XAnim video driver (process handling implementation)
69 wxVideoXANIMProcess::wxVideoXANIMProcess(wxVideoXANIM
*xanim
)
74 void wxVideoXANIMProcess::OnTerminate(int WXUNUSED(pid
), int WXUNUSED(status
))
76 m_vid_xanim
->m_xanim_started
= false;
77 m_vid_xanim
->OnFinished();
80 wxVideoXANIMOutput::wxVideoXANIMOutput()
81 : wxProcess(NULL
, wxID_ANY
)
87 bool wxVideoXANIMOutput::IsTerminated() const
92 void wxVideoXANIMOutput::OnTerminate(int pid
, int status
)
97 // -------------------------------------------------------------------------
98 // XAnim video driver (implementation)
100 wxVideoXANIM::wxVideoXANIM()
101 : wxVideoBaseDriver()
103 m_internal
= new wxXANIMinternal
;
104 m_xanim_detector
= new wxVideoXANIMProcess(this);
105 m_xanim_started
= false;
107 m_filename
= wxEmptyString
;
108 m_remove_file
= false;
111 wxVideoXANIM::wxVideoXANIM(wxInputStream
& str
)
112 : wxVideoBaseDriver(str
)
114 m_internal
= new wxXANIMinternal
;
115 m_xanim_detector
= new wxVideoXANIMProcess(this);
116 m_xanim_started
= false;
121 m_filename
= wxGetTempFileName(_T("vidxa"));
122 m_remove_file
= true;
123 wxFileOutputStream
fout(m_filename
);
130 wxVideoXANIM::wxVideoXANIM(const wxString
& filename
)
132 m_internal
= new wxXANIMinternal
;
133 m_xanim_detector
= new wxVideoXANIMProcess(this);
134 m_xanim_started
= false;
137 m_filename
= filename
;
138 m_remove_file
= false;
145 wxVideoXANIM::~wxVideoXANIM()
150 delete m_xanim_detector
;
153 wxRemoveFile(m_filename
);
156 // -------------------------------------------------------------------------
159 bool wxVideoXANIM::Play()
161 if (!m_paused
&& m_xanim_started
)
163 if (!m_video_output
) {
164 wxVideoCreateFrame(this);
168 // The movie starts with xanim
169 if (RestartXANIM()) {
176 bool wxVideoXANIM::Pause()
178 if (!m_paused
&& SendCommand(" ")) {
185 bool wxVideoXANIM::Resume()
187 if (m_paused
&& SendCommand(" ")) {
194 bool wxVideoXANIM::Stop()
196 if (!m_xanim_started
)
201 // We are waiting for the termination of the subprocess.
202 while (m_xanim_started
) {
211 // -------------------------------------------------------------------------
212 // Movie size controller
214 bool wxVideoXANIM::SetSize(wxSize size
)
219 m_video_output
->SetSize(size
.GetWidth(), size
.GetHeight());
223 bool wxVideoXANIM::GetSize(wxSize
& size
) const
227 size
.Set(m_size
[0], m_size
[1]);
231 // -------------------------------------------------------------------------
232 // Capabilities of XAnim
234 bool wxVideoXANIM::IsCapable(wxVideoType v_type
) const
236 if (v_type
== wxVIDEO_MSAVI
|| v_type
== wxVIDEO_MPEG
||
237 v_type
== wxVIDEO_QT
|| v_type
== wxVIDEO_GIF
|| v_type
== wxVIDEO_JMOV
||
238 v_type
== wxVIDEO_FLI
|| v_type
== wxVIDEO_IFF
|| v_type
== wxVIDEO_SGI
)
244 // -------------------------------------------------------------------------
247 wxString
wxVideoXANIM::GetMovieCodec() const
254 wxString
wxVideoXANIM::GetAudioCodec() const
261 wxUint32
wxVideoXANIM::GetSampleRate() const
268 wxUint8
wxVideoXANIM::GetChannels() const
275 wxUint8
wxVideoXANIM::GetBPS() const
282 double wxVideoXANIM::GetFrameRate() const
289 wxUint32
wxVideoXANIM::GetNbFrames() const
297 bool wxVideoXANIM::IsPaused() const
302 bool wxVideoXANIM::IsStopped() const
304 return !m_xanim_started
;
307 // -------------------------------------------------------------------------
310 bool wxVideoXANIM::AttachOutput(wxWindow
& out
)
312 if (!wxVideoBaseDriver::AttachOutput(out
))
318 void wxVideoXANIM::DetachOutput()
321 m_xanim_started
= false;
324 wxVideoBaseDriver::DetachOutput();
327 // -------------------------------------------------------------------------
328 // Lowlevel XAnim controller
330 bool wxVideoXANIM::SendCommand(const char *command
, char **ret
,
333 if (!m_xanim_started
)
337 // Send a command to XAnim through X11 Property
338 XChangeProperty(m_internal
->xanim_dpy
, m_internal
->xanim_window
,
339 m_internal
->xanim_atom
,
340 XA_STRING
, 8, PropModeReplace
, (unsigned char *)command
,
342 XFlush(m_internal
->xanim_dpy
);
348 XGetWindowProperty(m_internal
->xanim_dpy
, m_internal
->xanim_window
,
349 m_internal
->xanim_ret
, 0, 16, True
, AnyPropertyType
,
350 &prop_type
, &prop_format
, (unsigned long *)size
,
351 &extra
, (unsigned char **)ret
);
356 bool wxVideoXANIM::CollectInfo()
358 wxVideoXANIMOutput
*xanimProcess
;
359 wxString xanim_command
;
360 wxStringTokenizer tokenizer
;
362 xanimProcess
= new wxVideoXANIMOutput
;
363 xanim_command
= wxT("xanim +v +Zv -Ae ");
364 xanim_command
+= m_filename
;
365 if (!wxExecute(xanim_command
, false, xanimProcess
))
368 wxInputStream
*infoStream
= xanimProcess
->GetInputStream();
369 wxString totalOutput
;
371 while (infoStream
->GetLastError() == wxSTREAM_NO_ERROR
) {
374 infoStream
->Read(line
, sizeof(line
)-1);
375 if (infoStream
->LastRead() == 0)
378 line
[infoStream
->LastRead()] = 0;
380 totalOutput
+= wxString::FromAscii(line
);
383 // This is good for everything ... :-)
384 int position
= totalOutput
.Find(wxT("Video Codec:"));
386 totalOutput
.Remove(0, position
+13);
388 position
= totalOutput
.Find(wxT("depth="));
389 m_movieCodec
= totalOutput(0, position
);
391 totalOutput
.Remove(0, position
);
392 tokenizer
.SetString(totalOutput
, wxT("\n\r"));
394 // the rest of the line
395 wxString token
= tokenizer
.GetNextToken();
396 unsigned long my_long
;
399 totalOutput.ToULong(&my_long); \
403 totalOutput
= tokenizer
.GetString();
404 totalOutput
.Remove(0, totalOutput
.Find(wxT(":"))+2);
406 position
= totalOutput
.Find(wxT("Rate"));
407 m_audioCodec
= totalOutput(0, position
-1);
410 totalOutput
.Remove(0, totalOutput
.Find(wxT("="))+1);
411 GETINT(m_sampleRate
);
413 totalOutput
.Remove(0, totalOutput
.Find(wxT("="))+1);
416 totalOutput
.Remove(0, totalOutput
.Find(wxT("="))+1);
419 tokenizer
.Reinit(totalOutput
);
420 tokenizer
.GetNextToken();
421 totalOutput
= tokenizer
.GetString();
422 totalOutput
.Remove(0, totalOutput
.Find(wxT(":"))+2);
424 totalOutput
.Remove(0, totalOutput
.Find(wxT("="))+1);
427 totalOutput
.Remove(0,1);
430 totalOutput
.Remove(0, totalOutput
.Find(wxT("="))+1);
433 totalOutput
.Remove(0, totalOutput
.Find(wxT("="))+1);
434 totalOutput
.ToDouble(&m_frameRate
);
436 // We wait for the conclusion
437 while (!xanimProcess
->IsTerminated())
445 bool wxVideoXANIM::RestartXANIM()
447 wxString xanim_command
;
451 unsigned long nitems
;
456 if (!m_video_output
|| m_xanim_started
)
459 // Check if we can change the size of the window dynamicly
460 xanim_chg_size
= true;
461 // Get current display
463 m_internal
->xanim_dpy
= gdk_display
;
464 GtkPizza
*pizza
= GTK_PIZZA( m_video_output
->m_wxwindow
);
465 GdkWindow
*window
= pizza
->bin_window
;
467 m_internal
->xanim_window
= GDK_WINDOW_XWINDOW(window
);
469 // Get the XANIM atom
470 m_internal
->xanim_atom
= XInternAtom(m_internal
->xanim_dpy
,
471 "XANIM_PROPERTY", False
);
474 xanim_command
.Printf(
475 wxT("xanim -Zr +Ze +Sr +f +W%d +f +q +Av70 %s %s"),
476 (int)m_internal
->xanim_window
,
477 (xanim_chg_size
) ? _T("") : _T(""), // ??? why ???
478 WXSTRINGCAST m_filename
);
481 if (!wxExecute(xanim_command
, false, m_xanim_detector
))
484 // Wait for XAnim to be ready
486 m_xanim_started
= true;
487 while (nitems
== 0 && m_xanim_started
) {
488 ret
= XGetWindowProperty(m_internal
->xanim_dpy
, m_internal
->xanim_window
,
489 m_internal
->xanim_atom
,
490 0, 4, False
, AnyPropertyType
, &prop_type
,
491 &prop_format
, &nitems
, &extra
,
492 (unsigned char **)&prop
);
498 vibrato_size
= m_video_output
->GetSize();
500 vibrato_size
.SetWidth(vibrato_size
.GetWidth()+1);
501 m_video_output
->SetSize(vibrato_size
);
502 vibrato_size
.SetWidth(vibrato_size
.GetWidth()-1);
503 m_video_output
->SetSize(vibrato_size
);
504 // Very useful ! Actually it "should" sends a SETSIZE event to XAnim
505 // FIXME: This event is not sent !!