]> git.saurik.com Git - wxWidgets.git/blob - utils/wxMMedia2/lib/vidxanm.cpp
Ok. Vidwin works again on Windows.
[wxWidgets.git] / utils / wxMMedia2 / lib / vidxanm.cpp
1 // -------------------------------------------------------------------------
2 // Name: vidxanm.cpp
3 // Purpose: wxMMedia
4 // Author: Guilhem Lavaux
5 // Created: 1997
6 // Updated: 1998
7 // Copyright: (C) 1997, 1998, 1999 Guilhem Lavaux
8 // License: wxWindows license
9 // -------------------------------------------------------------------------
10
11 #ifdef __GNUG__
12 #pragma implementation "vidxanm.h"
13 #endif
14
15 #include <wx/wxprec.h>
16
17 #ifndef WX_PRECOMP
18 #include <wx/wx.h>
19 #endif
20
21 // Pizza !
22 #include <wx/gtk/win_gtk.h>
23
24 #include <X11/Xlib.h>
25 #include <X11/Intrinsic.h>
26 #ifdef __WXGTK__
27 #include <gtk/gtkwidget.h>
28 #include <gtk/gtkwindow.h>
29 #include <gdk/gdk.h>
30 #include <gdk/gdkprivate.h>
31 #endif
32
33 #include <wx/filefn.h>
34 #include <wx/wfstream.h>
35 #include <wx/datstrm.h>
36 #include <wx/tokenzr.h>
37
38 #define WXMMEDIA_INTERNAL
39 #include "vidbase.h"
40 #include "vidxanm.h"
41
42 IMPLEMENT_DYNAMIC_CLASS(wxVideoXANIM, wxVideoBaseDriver)
43
44 // -------------------------------------------------------------------------
45 // End process detector
46
47 class wxVideoXANIMProcess: public wxProcess {
48 public:
49 wxVideoXANIMProcess(wxVideoXANIM *xanim);
50
51 void OnTerminate(int pid, int status);
52
53 protected:
54 wxVideoXANIM *m_vid_xanim;
55 };
56
57 class wxVideoXANIMOutput: public wxProcess {
58 public:
59 wxVideoXANIMOutput();
60
61 void OnTerminate(int pid, int status);
62
63 bool IsTerminated() const;
64 protected:
65 bool m_terminated;
66 };
67
68 // -------------------------------------------------------------------------
69 // XAnim video driver (process handling implementation)
70
71 wxVideoXANIMProcess::wxVideoXANIMProcess(wxVideoXANIM *xanim)
72 {
73 m_vid_xanim = xanim;
74 }
75
76 void wxVideoXANIMProcess::OnTerminate(int WXUNUSED(pid), int WXUNUSED(status))
77 {
78 m_vid_xanim->m_xanim_started = FALSE;
79 m_vid_xanim->OnFinished();
80 }
81
82 wxVideoXANIMOutput::wxVideoXANIMOutput()
83 : wxProcess(NULL, TRUE, -1)
84 {
85 m_terminated = FALSE;
86 }
87
88 bool wxVideoXANIMOutput::IsTerminated() const
89 {
90 return m_terminated;
91 }
92
93 void wxVideoXANIMOutput::OnTerminate(int pid, int status)
94 {
95 m_terminated = TRUE;
96 }
97
98 // -------------------------------------------------------------------------
99 // XAnim video driver (implementation)
100
101 wxVideoXANIM::wxVideoXANIM()
102 : wxVideoBaseDriver()
103 {
104 m_internal = new wxXANIMinternal;
105 m_xanim_detector = new wxVideoXANIMProcess(this);
106 m_xanim_started = FALSE;
107 m_paused = FALSE;
108 m_filename = "";
109 m_remove_file = FALSE;
110 }
111
112 wxVideoXANIM::wxVideoXANIM(wxInputStream& str)
113 : wxVideoBaseDriver(str)
114 {
115 m_internal = new wxXANIMinternal;
116 m_xanim_detector = new wxVideoXANIMProcess(this);
117 m_xanim_started = FALSE;
118 m_paused = FALSE;
119 m_size[0] = 0;
120 m_size[1] = 0;
121
122 m_filename = wxGetTempFileName("vidxa");
123 m_remove_file = TRUE;
124 wxFileOutputStream fout(m_filename);
125
126 fout << str;
127
128 CollectInfo();
129 }
130
131 wxVideoXANIM::wxVideoXANIM(const wxString& filename)
132 {
133 m_internal = new wxXANIMinternal;
134 m_xanim_detector = new wxVideoXANIMProcess(this);
135 m_xanim_started = FALSE;
136 m_paused = FALSE;
137
138 m_filename = filename;
139 m_remove_file = FALSE;
140 m_size[0] = 0;
141 m_size[1] = 0;
142
143 CollectInfo();
144 }
145
146 wxVideoXANIM::~wxVideoXANIM()
147 {
148 if (m_xanim_started)
149 Stop();
150 delete m_internal;
151 delete m_xanim_detector;
152
153 if (m_remove_file)
154 wxRemoveFile(m_filename);
155 }
156
157 // -------------------------------------------------------------------------
158 // Movie controller
159
160 bool wxVideoXANIM::Play()
161 {
162 if (!m_paused && m_xanim_started)
163 return TRUE;
164 if (!m_video_output) {
165 wxVideoCreateFrame(this);
166 return TRUE;
167 }
168
169 // The movie starts with xanim
170 if (RestartXANIM()) {
171 m_paused = FALSE;
172 return TRUE;
173 }
174 return FALSE;
175 }
176
177 bool wxVideoXANIM::Pause()
178 {
179 if (!m_paused && SendCommand(" ")) {
180 m_paused = TRUE;
181 return TRUE;
182 }
183 return FALSE;
184 }
185
186 bool wxVideoXANIM::Resume()
187 {
188 if (m_paused && SendCommand(" ")) {
189 m_paused = FALSE;
190 return TRUE;
191 }
192 return FALSE;
193 }
194
195 bool wxVideoXANIM::Stop()
196 {
197 if (!m_xanim_started)
198 return FALSE;
199
200 SendCommand("q");
201
202 // We are waiting for the termination of the subprocess.
203 while (m_xanim_started) {
204 wxYield();
205 }
206
207 m_paused = FALSE;
208
209 return TRUE;
210 }
211
212 // -------------------------------------------------------------------------
213 // Movie size controller
214
215 bool wxVideoXANIM::SetSize(wxSize size)
216 {
217 if (!m_video_output)
218 return FALSE;
219
220 m_video_output->SetSize(size.GetWidth(), size.GetHeight());
221 return FALSE;
222 }
223
224 bool wxVideoXANIM::GetSize(wxSize& size) const
225 {
226 if (m_size[0] == 0)
227 return FALSE;
228 size.Set(m_size[0], m_size[1]);
229 return TRUE;
230 }
231
232 // -------------------------------------------------------------------------
233 // Capabilities of XAnim
234
235 bool wxVideoXANIM::IsCapable(wxVideoType v_type) const
236 {
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)
240 return TRUE;
241 else
242 return FALSE;
243 }
244
245 // -------------------------------------------------------------------------
246 // Movie state
247
248 wxString wxVideoXANIM::GetMovieCodec() const
249 {
250 if (m_size[0] == 0)
251 return wxT("");
252 return m_movieCodec;
253 }
254
255 wxString wxVideoXANIM::GetAudioCodec() const
256 {
257 if (m_size[0] == 0)
258 return wxT("");
259 return m_audioCodec;
260 }
261
262 wxUint32 wxVideoXANIM::GetSampleRate() const
263 {
264 if (m_size[0] == 0)
265 return 0;
266 return m_sampleRate;
267 }
268
269 wxUint8 wxVideoXANIM::GetChannels() const
270 {
271 if (m_size[0] == 0)
272 return 0;
273 return m_channels;
274 }
275
276 wxUint8 wxVideoXANIM::GetBPS() const
277 {
278 if (m_size[0] == 0)
279 return 0;
280 return m_bps;
281 }
282
283 double wxVideoXANIM::GetFrameRate() const
284 {
285 if (m_size[0] == 0)
286 return 0.0;
287 return m_frameRate;
288 }
289
290 wxUint32 wxVideoXANIM::GetNbFrames() const
291 {
292 if (m_size[0] == 0)
293 return 0;
294 return m_frames;
295 }
296
297
298 bool wxVideoXANIM::IsPaused() const
299 {
300 return m_paused;
301 }
302
303 bool wxVideoXANIM::IsStopped() const
304 {
305 return !m_xanim_started;
306 }
307
308 // -------------------------------------------------------------------------
309 // Output management
310
311 bool wxVideoXANIM::AttachOutput(wxWindow& out)
312 {
313 if (!wxVideoBaseDriver::AttachOutput(out))
314 return FALSE;
315
316 return TRUE;
317 }
318
319 void wxVideoXANIM::DetachOutput()
320 {
321 SendCommand("q");
322 m_xanim_started = FALSE;
323 m_paused = FALSE;
324
325 wxVideoBaseDriver::DetachOutput();
326 }
327
328 // -------------------------------------------------------------------------
329 // Lowlevel XAnim controller
330
331 bool wxVideoXANIM::SendCommand(const char *command, char **ret,
332 wxUint32 *size)
333 {
334 if (!m_xanim_started)
335 if (!RestartXANIM())
336 return FALSE;
337
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,
342 strlen(command));
343 XFlush(m_internal->xanim_dpy);
344 if (ret) {
345 int prop_format;
346 Atom prop_type;
347 unsigned long extra;
348
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);
353 }
354 return TRUE;
355 }
356
357 bool wxVideoXANIM::CollectInfo()
358 {
359 wxVideoXANIMOutput *xanimProcess;
360 wxString xanim_command;
361 wxStringTokenizer tokenizer;
362
363 xanimProcess = new wxVideoXANIMOutput;
364 xanim_command = wxT("xanim +v +Zv -Ae ");
365 xanim_command += m_filename;
366 if (!wxExecute(xanim_command, FALSE, xanimProcess))
367 return FALSE;
368
369 wxInputStream *infoStream = xanimProcess->GetInputStream();
370 wxString totalOutput;
371
372 while (infoStream->LastError() == wxSTREAM_NOERROR) {
373 char line[100];
374
375 infoStream->Read(line, sizeof(line)-1);
376 if (infoStream->LastRead() == 0)
377 break;
378
379 line[infoStream->LastRead()] = 0;
380
381 totalOutput += line;
382 }
383
384 // This is good for everything ... :-)
385 int position = totalOutput.Find(wxT("Video Codec:"));
386
387 totalOutput.Remove(0, position+13);
388
389 position = totalOutput.Find(wxT("depth="));
390 m_movieCodec = totalOutput(0, position);
391
392 totalOutput.Remove(0, position);
393 tokenizer.SetString(totalOutput, "\n\r");
394
395 // the rest of the line
396 wxString token = tokenizer.GetNextToken();
397 unsigned long my_long;
398
399 #define GETINT(i) \
400 totalOutput.ToULong(&my_long); \
401 i = my_long;
402
403 // 'Audio Codec:'
404 totalOutput = tokenizer.GetString();
405 totalOutput.Remove(0, totalOutput.Find(wxT(":"))+2);
406
407 position = totalOutput.Find(wxT("Rate"));
408 m_audioCodec = totalOutput(0, position-1);
409
410 // 'Rate='
411 totalOutput.Remove(0, totalOutput.Find(wxT("="))+1);
412 GETINT(m_sampleRate);
413 // 'Chans='
414 totalOutput.Remove(0, totalOutput.Find(wxT("="))+1);
415 GETINT(m_channels);
416 // 'Bps='
417 totalOutput.Remove(0, totalOutput.Find(wxT("="))+1);
418 GETINT(m_bps);
419 // 'Frame Stats:'
420 tokenizer.Reinit(totalOutput);
421 tokenizer.GetNextToken();
422 totalOutput = tokenizer.GetString();
423 totalOutput.Remove(0, totalOutput.Find(wxT(":"))+2);
424 // 'Size='
425 totalOutput.Remove(0, totalOutput.Find(wxT("="))+1);
426 GETINT(m_size[0]);
427 // 'x'
428 totalOutput.Remove(0,1);
429 GETINT(m_size[1]);
430 // 'Frames='
431 totalOutput.Remove(0, totalOutput.Find(wxT("="))+1);
432 GETINT(m_frames);
433 // 'avfps='
434 totalOutput.Remove(0, totalOutput.Find(wxT("="))+1);
435 totalOutput.ToDouble(&m_frameRate);
436
437 // We wait for the conclusion
438 while (!xanimProcess->IsTerminated())
439 wxYield();
440
441 delete xanimProcess;
442
443 return TRUE;
444 }
445
446 bool wxVideoXANIM::RestartXANIM()
447 {
448 wxString xanim_command;
449 int ret;
450 Atom prop_type;
451 int prop_format;
452 unsigned long nitems;
453 unsigned long extra;
454 char prop[4];
455 bool xanim_chg_size;
456
457 if (!m_video_output || m_xanim_started)
458 return FALSE;
459
460 // Check if we can change the size of the window dynamicly
461 xanim_chg_size = TRUE;
462 // Get current display
463 #ifdef __WXGTK__
464 m_internal->xanim_dpy = gdk_display;
465 GtkPizza *pizza = GTK_PIZZA( m_video_output->m_wxwindow );
466 GdkWindow *window = pizza->bin_window;
467
468 m_internal->xanim_window =
469 ((GdkWindowPrivate *)window)->xwindow;
470 #endif
471 // Get the XANIM atom
472 m_internal->xanim_atom = XInternAtom(m_internal->xanim_dpy,
473 "XANIM_PROPERTY", False);
474
475 // Build the command
476 xanim_command.Printf(wxT("xanim -Zr +Ze +Sr +f +W%d +f +q "
477 "+Av70 %s %s"), m_internal->xanim_window,
478 (xanim_chg_size) ? _T("") : _T(""),
479 WXSTRINGCAST m_filename);
480
481 // Execute it
482 if (!wxExecute(xanim_command, FALSE, m_xanim_detector))
483 return FALSE;
484
485 // Wait for XAnim to be ready
486 nitems = 0;
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);
494 wxYield();
495 }
496
497 wxSize vibrato_size;
498
499 vibrato_size = m_video_output->GetSize();
500
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 sends a SETSIZE event to XAnim
506
507 m_paused = FALSE;
508
509 return TRUE;
510 }