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>
29 #include <gdk/gdkprivate.h>
32 #include "wx/filefn.h"
33 #include "wx/wfstream.h"
34 #include "wx/datstrm.h"
35 #include "wx/tokenzr.h"
37 #define WXMMEDIA_INTERNAL
38 #include "wx/mmedia/vidbase.h"
39 #include "wx/mmedia/vidxanm.h"
41 IMPLEMENT_DYNAMIC_CLASS(wxVideoXANIM
, wxVideoBaseDriver
)
43 // -------------------------------------------------------------------------
44 // End process detector
46 class wxVideoXANIMProcess
: public wxProcess
{
48 wxVideoXANIMProcess(wxVideoXANIM
*xanim
);
50 void OnTerminate(int pid
, int status
);
53 wxVideoXANIM
*m_vid_xanim
;
56 class wxVideoXANIMOutput
: public wxProcess
{
60 void OnTerminate(int pid
, int status
);
62 bool IsTerminated() const;
67 // -------------------------------------------------------------------------
68 // XAnim video driver (process handling implementation)
70 wxVideoXANIMProcess::wxVideoXANIMProcess(wxVideoXANIM
*xanim
)
75 void wxVideoXANIMProcess::OnTerminate(int WXUNUSED(pid
), int WXUNUSED(status
))
77 m_vid_xanim
->m_xanim_started
= false;
78 m_vid_xanim
->OnFinished();
81 wxVideoXANIMOutput::wxVideoXANIMOutput()
82 : wxProcess(NULL
, wxID_ANY
)
88 bool wxVideoXANIMOutput::IsTerminated() const
93 void wxVideoXANIMOutput::OnTerminate(int pid
, int status
)
98 // -------------------------------------------------------------------------
99 // XAnim video driver (implementation)
101 wxVideoXANIM::wxVideoXANIM()
102 : wxVideoBaseDriver()
104 m_internal
= new wxXANIMinternal
;
105 m_xanim_detector
= new wxVideoXANIMProcess(this);
106 m_xanim_started
= false;
108 m_filename
= wxEmptyString
;
109 m_remove_file
= false;
112 wxVideoXANIM::wxVideoXANIM(wxInputStream
& str
)
113 : wxVideoBaseDriver(str
)
115 m_internal
= new wxXANIMinternal
;
116 m_xanim_detector
= new wxVideoXANIMProcess(this);
117 m_xanim_started
= false;
122 m_filename
= wxGetTempFileName(_T("vidxa"));
123 m_remove_file
= true;
124 wxFileOutputStream
fout(m_filename
);
131 wxVideoXANIM::wxVideoXANIM(const wxString
& filename
)
133 m_internal
= new wxXANIMinternal
;
134 m_xanim_detector
= new wxVideoXANIMProcess(this);
135 m_xanim_started
= false;
138 m_filename
= filename
;
139 m_remove_file
= false;
146 wxVideoXANIM::~wxVideoXANIM()
151 delete m_xanim_detector
;
154 wxRemoveFile(m_filename
);
157 // -------------------------------------------------------------------------
160 bool wxVideoXANIM::Play()
162 if (!m_paused
&& m_xanim_started
)
164 if (!m_video_output
) {
165 wxVideoCreateFrame(this);
169 // The movie starts with xanim
170 if (RestartXANIM()) {
177 bool wxVideoXANIM::Pause()
179 if (!m_paused
&& SendCommand(" ")) {
186 bool wxVideoXANIM::Resume()
188 if (m_paused
&& SendCommand(" ")) {
195 bool wxVideoXANIM::Stop()
197 if (!m_xanim_started
)
202 // We are waiting for the termination of the subprocess.
203 while (m_xanim_started
) {
212 // -------------------------------------------------------------------------
213 // Movie size controller
215 bool wxVideoXANIM::SetSize(wxSize size
)
220 m_video_output
->SetSize(size
.GetWidth(), size
.GetHeight());
224 bool wxVideoXANIM::GetSize(wxSize
& size
) const
228 size
.Set(m_size
[0], m_size
[1]);
232 // -------------------------------------------------------------------------
233 // Capabilities of XAnim
235 bool wxVideoXANIM::IsCapable(wxVideoType v_type
) const
237 if (v_type
== wxVIDEO_MSAVI
|| v_type
== wxVIDEO_MPEG
||
238 v_type
== wxVIDEO_QT
|| v_type
== wxVIDEO_GIF
|| v_type
== wxVIDEO_JMOV
||
239 v_type
== wxVIDEO_FLI
|| v_type
== wxVIDEO_IFF
|| v_type
== wxVIDEO_SGI
)
245 // -------------------------------------------------------------------------
248 wxString
wxVideoXANIM::GetMovieCodec() const
255 wxString
wxVideoXANIM::GetAudioCodec() const
262 wxUint32
wxVideoXANIM::GetSampleRate() const
269 wxUint8
wxVideoXANIM::GetChannels() const
276 wxUint8
wxVideoXANIM::GetBPS() const
283 double wxVideoXANIM::GetFrameRate() const
290 wxUint32
wxVideoXANIM::GetNbFrames() const
298 bool wxVideoXANIM::IsPaused() const
303 bool wxVideoXANIM::IsStopped() const
305 return !m_xanim_started
;
308 // -------------------------------------------------------------------------
311 bool wxVideoXANIM::AttachOutput(wxWindow
& out
)
313 if (!wxVideoBaseDriver::AttachOutput(out
))
319 void wxVideoXANIM::DetachOutput()
322 m_xanim_started
= false;
325 wxVideoBaseDriver::DetachOutput();
328 // -------------------------------------------------------------------------
329 // Lowlevel XAnim controller
331 bool wxVideoXANIM::SendCommand(const char *command
, char **ret
,
334 if (!m_xanim_started
)
338 // Send a command to XAnim through X11 Property
339 XChangeProperty(m_internal
->xanim_dpy
, m_internal
->xanim_window
,
340 m_internal
->xanim_atom
,
341 XA_STRING
, 8, PropModeReplace
, (unsigned char *)command
,
343 XFlush(m_internal
->xanim_dpy
);
349 XGetWindowProperty(m_internal
->xanim_dpy
, m_internal
->xanim_window
,
350 m_internal
->xanim_ret
, 0, 16, True
, AnyPropertyType
,
351 &prop_type
, &prop_format
, (unsigned long *)size
,
352 &extra
, (unsigned char **)ret
);
357 bool wxVideoXANIM::CollectInfo()
359 wxVideoXANIMOutput
*xanimProcess
;
360 wxString xanim_command
;
361 wxStringTokenizer tokenizer
;
363 xanimProcess
= new wxVideoXANIMOutput
;
364 xanim_command
= wxT("xanim +v +Zv -Ae ");
365 xanim_command
+= m_filename
;
366 if (!wxExecute(xanim_command
, false, xanimProcess
))
369 wxInputStream
*infoStream
= xanimProcess
->GetInputStream();
370 wxString totalOutput
;
372 while (infoStream
->GetLastError() == wxSTREAM_NO_ERROR
) {
375 infoStream
->Read(line
, sizeof(line
)-1);
376 if (infoStream
->LastRead() == 0)
379 line
[infoStream
->LastRead()] = 0;
381 totalOutput
+= wxString::FromAscii(line
);
384 // This is good for everything ... :-)
385 int position
= totalOutput
.Find(wxT("Video Codec:"));
387 totalOutput
.Remove(0, position
+13);
389 position
= totalOutput
.Find(wxT("depth="));
390 m_movieCodec
= totalOutput(0, position
);
392 totalOutput
.Remove(0, position
);
393 tokenizer
.SetString(totalOutput
, wxT("\n\r"));
395 // the rest of the line
396 wxString token
= tokenizer
.GetNextToken();
397 unsigned long my_long
;
400 totalOutput.ToULong(&my_long); \
404 totalOutput
= tokenizer
.GetString();
405 totalOutput
.Remove(0, totalOutput
.Find(wxT(":"))+2);
407 position
= totalOutput
.Find(wxT("Rate"));
408 m_audioCodec
= totalOutput(0, position
-1);
411 totalOutput
.Remove(0, totalOutput
.Find(wxT("="))+1);
412 GETINT(m_sampleRate
);
414 totalOutput
.Remove(0, totalOutput
.Find(wxT("="))+1);
417 totalOutput
.Remove(0, totalOutput
.Find(wxT("="))+1);
420 tokenizer
.Reinit(totalOutput
);
421 tokenizer
.GetNextToken();
422 totalOutput
= tokenizer
.GetString();
423 totalOutput
.Remove(0, totalOutput
.Find(wxT(":"))+2);
425 totalOutput
.Remove(0, totalOutput
.Find(wxT("="))+1);
428 totalOutput
.Remove(0,1);
431 totalOutput
.Remove(0, totalOutput
.Find(wxT("="))+1);
434 totalOutput
.Remove(0, totalOutput
.Find(wxT("="))+1);
435 totalOutput
.ToDouble(&m_frameRate
);
437 // We wait for the conclusion
438 while (!xanimProcess
->IsTerminated())
446 bool wxVideoXANIM::RestartXANIM()
448 wxString xanim_command
;
452 unsigned long nitems
;
457 if (!m_video_output
|| m_xanim_started
)
460 // Check if we can change the size of the window dynamicly
461 xanim_chg_size
= true;
462 // Get current display
464 m_internal
->xanim_dpy
= gdk_display
;
465 GtkPizza
*pizza
= GTK_PIZZA( m_video_output
->m_wxwindow
);
466 GdkWindow
*window
= pizza
->bin_window
;
468 m_internal
->xanim_window
= GDK_WINDOW_XWINDOW(window
);
470 // Get the XANIM atom
471 m_internal
->xanim_atom
= XInternAtom(m_internal
->xanim_dpy
,
472 "XANIM_PROPERTY", False
);
475 xanim_command
.Printf(
476 wxT("xanim -Zr +Ze +Sr +f +W%d +f +q +Av70 %s %s"),
477 (int)m_internal
->xanim_window
,
478 (xanim_chg_size
) ? _T("") : _T(""), // ??? why ???
479 WXSTRINGCAST m_filename
);
482 if (!wxExecute(xanim_command
, false, m_xanim_detector
))
485 // Wait for XAnim to be ready
487 m_xanim_started
= true;
488 while (nitems
== 0 && m_xanim_started
) {
489 ret
= XGetWindowProperty(m_internal
->xanim_dpy
, m_internal
->xanim_window
,
490 m_internal
->xanim_atom
,
491 0, 4, False
, AnyPropertyType
, &prop_type
,
492 &prop_format
, &nitems
, &extra
,
493 (unsigned char **)&prop
);
499 vibrato_size
= m_video_output
->GetSize();
501 vibrato_size
.SetWidth(vibrato_size
.GetWidth()+1);
502 m_video_output
->SetSize(vibrato_size
);
503 vibrato_size
.SetWidth(vibrato_size
.GetWidth()-1);
504 m_video_output
->SetSize(vibrato_size
);
505 // Very useful ! Actually it "should" sends a SETSIZE event to XAnim
506 // FIXME: This event is not sent !!