00001
00002 #include <signal.h>
00003
00004
00005 #include <iostream>
00006 #include <cstdlib>
00007 using namespace std;
00008
00009
00010 #include "mythlogging.h"
00011 #include "mythxdisplay.h"
00012 #include "util-xv.h"
00013
00014
00015 #include <X11/Xatom.h>
00016 #include <X11/Xutil.h>
00017 #include <X11/extensions/XShm.h>
00018 #include <X11/extensions/Xv.h>
00019 #include <X11/extensions/Xvlib.h>
00020
00021 QMap<int,port_info> open_xv_ports;
00022
00023 void close_all_xv_ports_signal_handler(int sig)
00024 {
00025 LOG(VB_GENERAL, LOG_INFO, QString("Signal: %1").arg(sys_siglist[sig]));
00026 QMap<int,port_info>::iterator it;
00027 for (it = open_xv_ports.begin(); it != open_xv_ports.end(); ++it)
00028 {
00029 restore_port_attributes((*it).port);
00030 LOG(VB_GENERAL, LOG_INFO, QString("Ungrabbing XVideo port: %1")
00031 .arg((*it).port));
00032 XvUngrabPort((*it).disp->GetDisplay(), (*it).port, CurrentTime);
00033 }
00034 exit(GENERIC_EXIT_NOT_OK);
00035 }
00036
00037 void save_port_attributes(int port)
00038 {
00039 if (!open_xv_ports.count(port))
00040 return;
00041
00042 open_xv_ports[port].attribs.clear();
00043
00044 int attrib_count = 0;
00045
00046 MythXDisplay *disp = open_xv_ports[port].disp;
00047 MythXLocker lock(disp);
00048 XvAttribute *attributes = XvQueryPortAttributes(disp->GetDisplay(),
00049 port, &attrib_count);
00050 if (!attributes || !attrib_count)
00051 return;
00052
00053 for (int i = 0; i < attrib_count; i++)
00054 {
00055 if (!(attributes[i].flags & XvGettable))
00056 continue;
00057
00058 int current;
00059 if (xv_get_attrib(disp, port, attributes[i].name, current))
00060 open_xv_ports[port].attribs[QString(attributes[i].name)] = current;
00061 }
00062 }
00063
00064 void restore_port_attributes(int port, bool clear)
00065 {
00066 if (!open_xv_ports.count(port))
00067 return;
00068 if (!open_xv_ports[port].attribs.size())
00069 return;
00070
00071 MythXDisplay *disp = open_xv_ports[port].disp;
00072 MythXLocker lock(disp);
00073
00074 QMap<QString,int>::iterator it;
00075 for (it = open_xv_ports[port].attribs.begin();
00076 it != open_xv_ports[port].attribs.end(); ++it)
00077 {
00078 QByteArray ascii_name = it.key().toAscii();
00079 const char *cname = ascii_name.constData();
00080 xv_set_attrib(disp, port, cname, it.value());
00081 }
00082
00083 if (clear)
00084 open_xv_ports[port].attribs.clear();
00085 }
00086
00087 bool add_open_xv_port(MythXDisplay *disp, int port)
00088 {
00089 bool ret = false;
00090 if (port >= 0)
00091 {
00092 open_xv_ports[port].disp = disp;
00093 open_xv_ports[port].port = port;
00094 QByteArray ascii_name = "XV_SET_DEFAULTS";
00095 const char *name = ascii_name.constData();
00096 ret = xv_is_attrib_supported(disp, port, name);
00097
00098 signal(SIGINT, close_all_xv_ports_signal_handler);
00099 }
00100 return ret;
00101 }
00102
00103 void del_open_xv_port(int port)
00104 {
00105 if (port >= 0)
00106 {
00107 open_xv_ports.remove(port);
00108
00109 if (!open_xv_ports.count())
00110 {
00111
00112 signal(SIGINT, SIG_DFL);
00113 }
00114 }
00115 }
00116
00117 bool has_open_xv_port(int port)
00118 {
00119 return open_xv_ports.find(port) != open_xv_ports.end();
00120 }
00121
00122 uint cnt_open_xv_port(void)
00123 {
00124 return open_xv_ports.count();
00125 }
00126
00127 QString xvflags2str(int flags)
00128 {
00129 QString str("");
00130 if (XvInputMask == (flags & XvInputMask))
00131 str.append("XvInputMask ");
00132 if (XvOutputMask == (flags & XvOutputMask))
00133 str.append("XvOutputMask ");
00134 if (XvVideoMask == (flags & XvVideoMask))
00135 str.append("XvVideoMask ");
00136 if (XvStillMask == (flags & XvStillMask))
00137 str.append("XvStillMask ");
00138 if (XvImageMask == (flags & XvImageMask))
00139 str.append("XvImageMask ");
00140 return str;
00141 }
00142
00143 bool xv_is_attrib_supported(
00144 MythXDisplay *disp, int port, const char *name,
00145 int *current_value, int *min_value, int *max_value)
00146 {
00147 Atom xv_atom;
00148 XvAttribute *attributes;
00149 int attrib_count;
00150 int ret;
00151
00152 int dummy;
00153 int *xv_val = (current_value) ? current_value : &dummy;
00154
00155 MythXLocker lock(disp);
00156 attributes = XvQueryPortAttributes(disp->GetDisplay(),
00157 port, &attrib_count);
00158 for (int i = (attributes) ? 0 : attrib_count; i < attrib_count; i++)
00159 {
00160 if (strcmp(attributes[i].name, name))
00161 continue;
00162
00163 if (min_value)
00164 *min_value = attributes[i].min_value;
00165
00166 if (max_value)
00167 *max_value = attributes[i].max_value;
00168
00169 if (!(attributes[i].flags & XvGettable))
00170 {
00171 XFree(attributes);
00172 return true;
00173 }
00174
00175 xv_atom = XInternAtom(disp->GetDisplay(), name, False);
00176 if (None == xv_atom)
00177 continue;
00178
00179 ret = XvGetPortAttribute(disp->GetDisplay(), port, xv_atom, xv_val);
00180 if (Success == ret)
00181 {
00182 XFree(attributes);
00183 return true;
00184 }
00185 }
00186
00187 if (attributes)
00188 XFree(attributes);
00189
00190 return false;
00191 }
00192
00193 bool xv_set_attrib(MythXDisplay *disp, int port, const char *name, int val)
00194 {
00195 Atom xv_atom;
00196 XLOCK(disp, xv_atom = XInternAtom(disp->GetDisplay(), name, False));
00197 if (xv_atom == None)
00198 return false;
00199
00200 int ret;
00201 XLOCK(disp, ret = XvSetPortAttribute(disp->GetDisplay(),
00202 port, xv_atom, val));
00203 if (Success != ret)
00204 return false;
00205
00206 return true;
00207 }
00208
00209 bool xv_get_attrib(MythXDisplay *disp, int port, const char *name, int &val)
00210 {
00211 Atom xv_atom;
00212 XLOCK(disp, xv_atom = XInternAtom(disp->GetDisplay(), name, False));
00213 if (xv_atom == None)
00214 return false;
00215
00216 int ret;
00217 XLOCK(disp, ret = XvGetPortAttribute(disp->GetDisplay(),
00218 port, xv_atom, &val));
00219 if (Success != ret)
00220 return false;
00221
00222 return true;
00223 }