Files
wxWidgets/utils/wxMMedia2/lib/vidxanm.cpp
Guilhem Lavaux 2018e574e7 Major changes in wxVidXANIM (support for output filtering)
Several API addings
Added process.cpp, process.h and utilsunx.cpp in wxMMedia directory
They should be moved to src/unix, src/common and include/wx to use them


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@6280 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2000-02-25 09:08:52 +00:00

511 lines
12 KiB
C++

// -------------------------------------------------------------------------
// Name: vidxanm.cpp
// Purpose: wxMMedia
// Author: Guilhem Lavaux
// Created: 1997
// Updated: 1998
// Copyright: (C) 1997, 1998, 1999 Guilhem Lavaux
// License: wxWindows license
// -------------------------------------------------------------------------
#ifdef __GNUG__
#pragma implementation "vidxanm.h"
#endif
#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
// Pizza !
#include <wx/gtk/win_gtk.h>
#include <X11/Xlib.h>
#include <X11/Intrinsic.h>
#ifdef __WXGTK__
#include <gtk/gtkwidget.h>
#include <gtk/gtkwindow.h>
#include <gdk/gdk.h>
#include <gdk/gdkprivate.h>
#endif
#include <wx/filefn.h>
#include <wx/wfstream.h>
#include <wx/datstrm.h>
#include <wx/tokenzr.h>
#define WXMMEDIA_INTERNAL
#include "vidbase.h"
#include "vidxanm.h"
IMPLEMENT_DYNAMIC_CLASS(wxVideoXANIM, wxVideoBaseDriver)
// -------------------------------------------------------------------------
// End process detector
class wxVideoXANIMProcess: public wxProcess {
public:
wxVideoXANIMProcess(wxVideoXANIM *xanim);
void OnTerminate(int pid, int status);
protected:
wxVideoXANIM *m_vid_xanim;
};
class wxVideoXANIMOutput: public wxProcess {
public:
wxVideoXANIMOutput();
void OnTerminate(int pid, int status);
bool IsTerminated() const;
protected:
bool m_terminated;
};
// -------------------------------------------------------------------------
// XAnim video driver (process handling implementation)
wxVideoXANIMProcess::wxVideoXANIMProcess(wxVideoXANIM *xanim)
{
m_vid_xanim = xanim;
}
void wxVideoXANIMProcess::OnTerminate(int WXUNUSED(pid), int WXUNUSED(status))
{
m_vid_xanim->m_xanim_started = FALSE;
m_vid_xanim->OnFinished();
}
wxVideoXANIMOutput::wxVideoXANIMOutput()
: wxProcess(NULL, TRUE, -1)
{
m_terminated = FALSE;
}
bool wxVideoXANIMOutput::IsTerminated() const
{
return m_terminated;
}
void wxVideoXANIMOutput::OnTerminate(int pid, int status)
{
m_terminated = TRUE;
}
// -------------------------------------------------------------------------
// XAnim video driver (implementation)
wxVideoXANIM::wxVideoXANIM()
: wxVideoBaseDriver()
{
m_internal = new wxXANIMinternal;
m_xanim_detector = new wxVideoXANIMProcess(this);
m_xanim_started = FALSE;
m_paused = FALSE;
m_filename = "";
m_remove_file = FALSE;
}
wxVideoXANIM::wxVideoXANIM(wxInputStream& str)
: wxVideoBaseDriver(str)
{
m_internal = new wxXANIMinternal;
m_xanim_detector = new wxVideoXANIMProcess(this);
m_xanim_started = FALSE;
m_paused = FALSE;
m_size[0] = 0;
m_size[1] = 0;
m_filename = wxGetTempFileName("vidxa");
m_remove_file = TRUE;
wxFileOutputStream fout(m_filename);
fout << str;
CollectInfo();
}
wxVideoXANIM::wxVideoXANIM(const wxString& filename)
{
m_internal = new wxXANIMinternal;
m_xanim_detector = new wxVideoXANIMProcess(this);
m_xanim_started = FALSE;
m_paused = FALSE;
m_filename = filename;
m_remove_file = FALSE;
m_size[0] = 0;
m_size[1] = 0;
CollectInfo();
}
wxVideoXANIM::~wxVideoXANIM()
{
if (m_xanim_started)
Stop();
delete m_internal;
delete m_xanim_detector;
if (m_remove_file)
wxRemoveFile(m_filename);
}
// -------------------------------------------------------------------------
// Movie controller
bool wxVideoXANIM::Play()
{
if (!m_paused && m_xanim_started)
return TRUE;
if (!m_video_output) {
wxVideoCreateFrame(this);
return TRUE;
}
// The movie starts with xanim
if (RestartXANIM()) {
m_paused = FALSE;
return TRUE;
}
return FALSE;
}
bool wxVideoXANIM::Pause()
{
if (!m_paused && SendCommand(" ")) {
m_paused = TRUE;
return TRUE;
}
return FALSE;
}
bool wxVideoXANIM::Resume()
{
if (m_paused && SendCommand(" ")) {
m_paused = FALSE;
return TRUE;
}
return FALSE;
}
bool wxVideoXANIM::Stop()
{
if (!m_xanim_started)
return FALSE;
SendCommand("q");
// We are waiting for the termination of the subprocess.
while (m_xanim_started) {
wxYield();
}
m_paused = FALSE;
return TRUE;
}
// -------------------------------------------------------------------------
// Movie size controller
bool wxVideoXANIM::SetSize(wxSize size)
{
if (!m_video_output)
return FALSE;
m_video_output->SetSize(size.GetWidth(), size.GetHeight());
return FALSE;
}
bool wxVideoXANIM::GetSize(wxSize& size) const
{
if (m_size[0] == 0)
return FALSE;
size.Set(m_size[0], m_size[1]);
return TRUE;
}
// -------------------------------------------------------------------------
// Capabilities of XAnim
bool wxVideoXANIM::IsCapable(wxVideoType v_type) const
{
if (v_type == wxVIDEO_MSAVI || v_type == wxVIDEO_MPEG ||
v_type == wxVIDEO_QT || v_type == wxVIDEO_GIF || v_type == wxVIDEO_JMOV ||
v_type == wxVIDEO_FLI || v_type == wxVIDEO_IFF || v_type == wxVIDEO_SGI)
return TRUE;
else
return FALSE;
}
// -------------------------------------------------------------------------
// Movie state
wxString wxVideoXANIM::GetMovieCodec() const
{
if (m_size[0] == 0)
return wxT("");
return m_movieCodec;
}
wxString wxVideoXANIM::GetAudioCodec() const
{
if (m_size[0] == 0)
return wxT("");
return m_audioCodec;
}
wxUint32 wxVideoXANIM::GetSampleRate() const
{
if (m_size[0] == 0)
return 0;
return m_sampleRate;
}
wxUint8 wxVideoXANIM::GetChannels() const
{
if (m_size[0] == 0)
return 0;
return m_channels;
}
wxUint8 wxVideoXANIM::GetBPS() const
{
if (m_size[0] == 0)
return 0;
return m_bps;
}
double wxVideoXANIM::GetFrameRate() const
{
if (m_size[0] == 0)
return 0.0;
return m_frameRate;
}
wxUint32 wxVideoXANIM::GetNbFrames() const
{
if (m_size[0] == 0)
return 0;
return m_frames;
}
bool wxVideoXANIM::IsPaused() const
{
return m_paused;
}
bool wxVideoXANIM::IsStopped() const
{
return !m_xanim_started;
}
// -------------------------------------------------------------------------
// Output management
bool wxVideoXANIM::AttachOutput(wxWindow& out)
{
if (!wxVideoBaseDriver::AttachOutput(out))
return FALSE;
return TRUE;
}
void wxVideoXANIM::DetachOutput()
{
SendCommand("q");
m_xanim_started = FALSE;
m_paused = FALSE;
wxVideoBaseDriver::DetachOutput();
}
// -------------------------------------------------------------------------
// Lowlevel XAnim controller
bool wxVideoXANIM::SendCommand(const char *command, char **ret,
wxUint32 *size)
{
if (!m_xanim_started)
if (!RestartXANIM())
return FALSE;
// Send a command to XAnim through X11 Property
XChangeProperty(m_internal->xanim_dpy, m_internal->xanim_window,
m_internal->xanim_atom,
XA_STRING, 8, PropModeReplace, (unsigned char *)command,
strlen(command));
XFlush(m_internal->xanim_dpy);
if (ret) {
int prop_format;
Atom prop_type;
unsigned long extra;
XGetWindowProperty(m_internal->xanim_dpy, m_internal->xanim_window,
m_internal->xanim_ret, 0, 16, True, AnyPropertyType,
&prop_type, &prop_format, (unsigned long *)size,
&extra, (unsigned char **)ret);
}
return TRUE;
}
bool wxVideoXANIM::CollectInfo()
{
wxVideoXANIMOutput *xanimProcess;
wxString xanim_command;
wxStringTokenizer tokenizer;
xanimProcess = new wxVideoXANIMOutput;
xanim_command = wxT("xanim +v +Zv -Ae ");
xanim_command += m_filename;
if (!wxExecute(xanim_command, FALSE, xanimProcess))
return FALSE;
wxInputStream *infoStream = xanimProcess->GetInputStream();
wxString totalOutput;
while (infoStream->LastError() == wxSTREAM_NOERROR) {
char line[100];
infoStream->Read(line, sizeof(line)-1);
if (infoStream->LastRead() == 0)
break;
line[infoStream->LastRead()] = 0;
totalOutput += line;
}
// This is good for everything ... :-)
int position = totalOutput.Find(wxT("Video Codec:"));
totalOutput.Remove(0, position+13);
position = totalOutput.Find(wxT("depth="));
m_movieCodec = totalOutput(0, position);
totalOutput.Remove(0, position);
tokenizer.SetString(totalOutput, "\n\r");
// the rest of the line
wxString token = tokenizer.GetNextToken();
unsigned long my_long;
#define GETINT(i) \
totalOutput.ToULong(&my_long); \
i = my_long;
// 'Audio Codec:'
totalOutput = tokenizer.GetString();
totalOutput.Remove(0, totalOutput.Find(wxT(":"))+2);
position = totalOutput.Find(wxT("Rate"));
m_audioCodec = totalOutput(0, position-1);
// 'Rate='
totalOutput.Remove(0, totalOutput.Find(wxT("="))+1);
GETINT(m_sampleRate);
// 'Chans='
totalOutput.Remove(0, totalOutput.Find(wxT("="))+1);
GETINT(m_channels);
// 'Bps='
totalOutput.Remove(0, totalOutput.Find(wxT("="))+1);
GETINT(m_bps);
// 'Frame Stats:'
tokenizer.Reinit(totalOutput);
tokenizer.GetNextToken();
totalOutput = tokenizer.GetString();
totalOutput.Remove(0, totalOutput.Find(wxT(":"))+2);
// 'Size='
totalOutput.Remove(0, totalOutput.Find(wxT("="))+1);
GETINT(m_size[0]);
// 'x'
totalOutput.Remove(0,1);
GETINT(m_size[1]);
// 'Frames='
totalOutput.Remove(0, totalOutput.Find(wxT("="))+1);
GETINT(m_frames);
// 'avfps='
totalOutput.Remove(0, totalOutput.Find(wxT("="))+1);
totalOutput.ToDouble(&m_frameRate);
// We wait for the conclusion
while (!xanimProcess->IsTerminated())
wxYield();
delete xanimProcess;
return TRUE;
}
bool wxVideoXANIM::RestartXANIM()
{
wxString xanim_command;
int ret;
Atom prop_type;
int prop_format;
unsigned long nitems;
unsigned long extra;
char prop[4];
bool xanim_chg_size;
if (!m_video_output || m_xanim_started)
return FALSE;
// Check if we can change the size of the window dynamicly
xanim_chg_size = TRUE;
// Get current display
#ifdef __WXGTK__
m_internal->xanim_dpy = gdk_display;
GtkPizza *pizza = GTK_PIZZA( m_video_output->m_wxwindow );
GdkWindow *window = pizza->bin_window;
m_internal->xanim_window =
((GdkWindowPrivate *)window)->xwindow;
#endif
// Get the XANIM atom
m_internal->xanim_atom = XInternAtom(m_internal->xanim_dpy,
"XANIM_PROPERTY", False);
// Build the command
xanim_command.Printf(wxT("xanim -Zr +Ze +Sr +f +W%d +f +q "
"+Av70 %s %s"), m_internal->xanim_window,
(xanim_chg_size) ? _T("") : _T(""),
WXSTRINGCAST m_filename);
// Execute it
if (!wxExecute(xanim_command, FALSE, m_xanim_detector))
return FALSE;
// Wait for XAnim to be ready
nitems = 0;
m_xanim_started = TRUE;
while (nitems == 0 && m_xanim_started) {
ret = XGetWindowProperty(m_internal->xanim_dpy, m_internal->xanim_window,
m_internal->xanim_atom,
0, 4, False, AnyPropertyType, &prop_type,
&prop_format, &nitems, &extra,
(unsigned char **)&prop);
wxYield();
}
wxSize vibrato_size;
vibrato_size = m_video_output->GetSize();
vibrato_size.SetWidth(vibrato_size.GetWidth()+1);
m_video_output->SetSize(vibrato_size);
vibrato_size.SetWidth(vibrato_size.GetWidth()-1);
m_video_output->SetSize(vibrato_size);
// Very useful ! Actually it sends a SETSIZE event to XAnim
m_paused = FALSE;
return TRUE;
}