"Fossies" - the Fresh Open Source Software Archive

Member "ssr-0.4.2/src/Global.h" (18 May 2020, 15689 Bytes) of package /linux/privat/ssr-0.4.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "Global.h" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 0.4.1_vs_0.4.2.

    1 /*
    2 Copyright (c) 2012-2020 Maarten Baert <maarten-baert@hotmail.com>
    3 
    4 This file is part of SimpleScreenRecorder.
    5 
    6 SimpleScreenRecorder is free software: you can redistribute it and/or modify
    7 it under the terms of the GNU General Public License as published by
    8 the Free Software Foundation, either version 3 of the License, or
    9 (at your option) any later version.
   10 
   11 SimpleScreenRecorder is distributed in the hope that it will be useful,
   12 but WITHOUT ANY WARRANTY; without even the implied warranty of
   13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14 GNU General Public License for more details.
   15 
   16 You should have received a copy of the GNU General Public License
   17 along with SimpleScreenRecorder.  If not, see <http://www.gnu.org/licenses/>.
   18 */
   19 
   20 #ifndef GLOBAL_H
   21 #define GLOBAL_H
   22 
   23 #include <QtGui>
   24 
   25 #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
   26 
   27 #include <QProcess>
   28 #include <QTimer>
   29 
   30 #include <QAction>
   31 #include <QApplication>
   32 #include <QDesktopServices>
   33 #include <QDesktopWidget>
   34 #include <QDialogButtonBox>
   35 #include <QFileDialog>
   36 #include <QInputDialog>
   37 #include <QMainWindow>
   38 #include <QMenu>
   39 #include <QMessageBox>
   40 #include <QProgressDialog>
   41 #include <QSystemTrayIcon>
   42 
   43 #include <QButtonGroup>
   44 #include <QCheckBox>
   45 #include <QComboBox>
   46 #include <QDateTimeEdit>
   47 #include <QGroupBox>
   48 #include <QLabel>
   49 #include <QLineEdit>
   50 #include <QPushButton>
   51 #include <QRadioButton>
   52 #include <QScrollArea>
   53 #include <QScrollBar>
   54 #include <QSpinBox>
   55 #include <QSplitter>
   56 #include <QTextBrowser>
   57 
   58 #include <QGridLayout>
   59 #include <QHBoxLayout>
   60 #include <QStackedLayout>
   61 #include <QVBoxLayout>
   62 
   63 #endif
   64 
   65 #include <cassert>
   66 #include <cstdio>
   67 #include <cstdlib>
   68 #include <ctime>
   69 #include <stdint.h>
   70 
   71 #include <fcntl.h>
   72 #include <pwd.h>
   73 #include <strings.h>
   74 #include <sys/ioctl.h>
   75 #include <sys/shm.h>
   76 #include <sys/stat.h>
   77 #include <sys/types.h>
   78 #include <sys/wait.h>
   79 #include <termios.h>
   80 #include <unistd.h>
   81 
   82 #include <array>
   83 #include <atomic>
   84 #include <deque>
   85 #include <limits>
   86 #include <memory>
   87 #include <mutex>
   88 #include <random>
   89 #include <set>
   90 #include <sstream>
   91 #include <thread>
   92 #include <vector>
   93 
   94 #include <QX11Info>
   95 #include <X11/Xlib.h>
   96 #include <X11/Xutil.h>
   97 #include <X11/extensions/Xfixes.h>
   98 #include <X11/extensions/Xinerama.h>
   99 #include <X11/extensions/XShm.h>
  100 #include <X11/extensions/XInput2.h>
  101 #include <X11/keysym.h>
  102 #include <X11/keysymdef.h>
  103 
  104 // replacement for Qt::WindowTransparentForInput.
  105 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
  106 #include <X11/extensions/shape.h>
  107 #endif
  108 
  109 // replacement for QX11Info::isPlatformX11()
  110 inline bool IsPlatformX11() {
  111 #if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
  112     if(!QX11Info::isPlatformX11())
  113         return false;
  114 #endif
  115     char *v = getenv("XDG_SESSION_TYPE");
  116     if(v != NULL) {
  117         if(strcasecmp(v, "x11") == 0)
  118             return true;
  119         if(strcasecmp(v, "wayland") == 0 || strcasecmp(v, "mir") == 0)
  120             return false;
  121     }
  122     char *d = getenv("DISPLAY");
  123     return (d != NULL);
  124 }
  125 
  126 // undefine problematic Xlib macros
  127 #undef Bool
  128 
  129 extern "C" {
  130 #include <libavformat/avformat.h>
  131 #include <libavcodec/avcodec.h>
  132 #include <libavutil/avutil.h>
  133 #include <libavutil/channel_layout.h>
  134 #include <libavutil/mathematics.h>
  135 #include <libavutil/pixfmt.h>
  136 #include <libavutil/samplefmt.h>
  137 #include <libswscale/swscale.h>
  138 }
  139 
  140 // Whether x86/x64 specific instructions should be used.
  141 #ifndef SSR_USE_X86_ASM
  142 #error SSR_USE_X86_ASM should be defined!
  143 #endif
  144 
  145 // Whether ffmpeg or libav version numbers should be used for tests. The ffmpeg version number is usually slightly higher,
  146 // so that's the default (deprecation warnings are better than compilation errors).
  147 #ifndef SSR_USE_FFMPEG_VERSIONS
  148 #error SSR_USE_FFMPEG_VERSIONS should be defined!
  149 #endif
  150 
  151 // Whether OpenGL recording should be used.
  152 #ifndef SSR_USE_OPENGL_RECORDING
  153 #error SSR_USE_OPENGL_RECORDING should be defined!
  154 #endif
  155 
  156 // Whether ALSA should be used.
  157 #ifndef SSR_USE_ALSA
  158 #error SSR_USE_ALSA should be defined!
  159 #endif
  160 
  161 // Whether PulseAudio should be used.
  162 #ifndef SSR_USE_PULSEAUDIO
  163 #error SSR_USE_PULSEAUDIO should be defined!
  164 #endif
  165 
  166 // Whether JACK should be used.
  167 #ifndef SSR_USE_JACK
  168 #error SSR_USE_JACK should be defined!
  169 #endif
  170 
  171 // Path to system-wide application directory (usually /usr/share/simplescreenrecorder).
  172 #ifndef SSR_SYSTEM_DIR
  173 #error SSR_SYSTEM_DIR should be defined!
  174 #endif
  175 
  176 // Maximum allowed image size (to avoid 32-bit integer overflow)
  177 #define SSR_MAX_IMAGE_SIZE 20000
  178 
  179 // generic macro to test version numbers
  180 #define TEST_MAJOR_MINOR(major, minor, required_major, required_minor) (major > required_major || (major == required_major && minor >= required_minor))
  181 
  182 // test GCC version
  183 #define TEST_GCC_VERSION(major, minor) TEST_MAJOR_MINOR(__GNUC__, __GNUC_MINOR__, major, minor)
  184 
  185 // 'override' was added in GCC 4.7
  186 #if !TEST_GCC_VERSION(4, 7)
  187 #define override
  188 #endif
  189 
  190 // std::atomic_thread_fence exists in GCC 4.6 but it doesn't link properly for some reason
  191 #if !TEST_GCC_VERSION(4, 7)
  192 #define atomic_thread_fence atomic_thread_fence_replacement
  193 namespace std {
  194 inline void atomic_thread_fence_replacement(memory_order) {
  195     __sync_synchronize();
  196 }
  197 }
  198 #endif
  199 
  200 // libav/ffmpeg API changes with version numbers are listed in their repositories in the file 'doc/APIchanges'
  201 // I recommend using the ffmpeg one:
  202 // http://git.videolan.org/?p=ffmpeg.git;a=blob;f=doc/APIchanges
  203 // This one lists version numbers for both ffmpeg and libav whereas libav just ignores ffmpeg.
  204 
  205 #if SSR_USE_FFMPEG_VERSIONS
  206 #define TEST_AV_VERSION(prefix, ffmpeg_major, ffmpeg_minor, libav_major, libav_minor) TEST_MAJOR_MINOR(prefix##_VERSION_MAJOR, prefix##_VERSION_MINOR, ffmpeg_major, ffmpeg_minor)
  207 #else
  208 #define TEST_AV_VERSION(prefix, ffmpeg_major, ffmpeg_minor, libav_major, libav_minor) TEST_MAJOR_MINOR(prefix##_VERSION_MAJOR, prefix##_VERSION_MINOR, libav_major, libav_minor)
  209 #endif
  210 
  211 // av_muxer_iterate: lavf 58.9.100 / ???
  212 #define SSR_USE_AV_MUXER_ITERATE                   TEST_AV_VERSION(LIBAVFORMAT, 58, 9, 999, 999)
  213 // av_register_all deprecated: lavf 58.9.100 / ???
  214 #define SSR_USE_AV_REGISTER_ALL_DEPRECATED         TEST_AV_VERSION(LIBAVFORMAT, 58, 9, 999, 999)
  215 // AVStream::codecpar: lavf 57.33.100 / 57.5.0
  216 #define SSR_USE_AVSTREAM_CODECPAR                  TEST_AV_VERSION(LIBAVFORMAT, 57, 33, 57, 5)
  217 // AVStream::time_base as time base hint: lavf 55.44.100 / 55.20.0
  218 #define SSR_USE_AVSTREAM_TIME_BASE                 TEST_AV_VERSION(LIBAVFORMAT, 55, 44, 55, 20)
  219 // avformat_network_init: lavf 53.19.0 / 53.13.0
  220 #define SSR_USE_AVFORMAT_NETWORK_INIT              TEST_AV_VERSION(LIBAVFORMAT, 53, 19, 53, 13)
  221 // avformat_new_stream: lavf 53.17.0 / 53.10.0
  222 #define SSR_USE_AVFORMAT_NEW_STREAM                TEST_AV_VERSION(LIBAVFORMAT, 53, 17, 53, 10)
  223 // avformat_query_codec: lavf 53.11.0 / 53.8.0
  224 #define SSR_USE_AVFORMAT_QUERY_CODEC               TEST_AV_VERSION(LIBAVFORMAT, 53, 11, 53, 8)
  225 // avformat_free_context: lavf 52.96.0 / 52.96.0
  226 #define SSR_USE_AVFORMAT_FREE_CONTEXT              TEST_AV_VERSION(LIBAVFORMAT, 52, 96, 52, 96)
  227 
  228 // av_codec_iterate: lavc 58.10.100 / ???
  229 #define SSR_USE_AV_CODEC_ITERATE                   TEST_AV_VERSION(LIBAVCODEC, 58, 10, 999, 999)
  230 // av_lockmgr_register deprecated: lavc 58.9.100 / ???
  231 #define SSR_USE_AV_LOCKMGR_REGISTER_DEPRECATED     TEST_AV_VERSION(LIBAVCODEC, 58, 9, 999, 999)
  232 // avcodec_send_packet, avcodec_receive_frame, avcodec_send_frame, avcodec_receive_packet: lavc 57.37.100 / ???
  233 #define SSR_USE_AVCODEC_SEND_RECEIVE               TEST_AV_VERSION(LIBAVCODEC, 57, 37, 999, 999)
  234 // av_packet_alloc: lavc 57.12.100 / 57.8.0
  235 #define SSR_USE_AV_PACKET_ALLOC                    TEST_AV_VERSION(LIBAVCODEC, 57, 12, 57, 8)
  236 // AV_CODEC_CAP_*, AV_CODEC_FLAG_*: lavc 56.56.100 / 56.35.0
  237 #define SSR_USE_AV_CODEC_CAP                       TEST_AV_VERSION(LIBAVCODEC, 56, 56, 56, 35)
  238 #define SSR_USE_AV_CODEC_FLAG                      TEST_AV_VERSION(LIBAVCODEC, 56, 56, 56, 35)
  239 // av_packet_rescale_ts: lavc 55.68.100 / 55.55.0
  240 #define SSR_USE_AV_PACKET_RESCALE_TS               TEST_AV_VERSION(LIBAVCODEC, 55, 68, 55, 55)
  241 // AVCodecContext::side_data_only_packets added: lavc 55.66.100 / 55.54.0
  242 #define SSR_USE_SIDE_DATA_ONLY_PACKETS             TEST_AV_VERSION(LIBAVCODEC, 55, 66, 55, 54)
  243 // AVCodecContext::side_data_only_packets deprecated: lavc 57.2 / 57.2
  244 // - ffmpeg: missing, commit: https://git.videolan.org/?p=ffmpeg.git;a=commit;h=6064f697a321174232a3fad351afb21150c3e9e5
  245 // - libav: missing, commit: https://git.libav.org/?p=libav.git;a=commit;h=6064f697a321174232a3fad351afb21150c3e9e5
  246 #define SSR_USE_SIDE_DATA_ONLY_PACKETS_DEPRECATED  TEST_AV_VERSION(LIBAVCODEC, 57, 2, 57, 2)
  247 // av_frame_alloc, av_frame_free: lavc 55.45.101 / 55.28.1
  248 #define SSR_USE_AV_FRAME_ALLOC                     TEST_AV_VERSION(LIBAVCODEC, 55, 45, 55, 28)
  249 #define SSR_USE_AV_FRAME_FREE                      SSR_USE_AV_FRAME_ALLOC
  250 // avcodec_free_frame: lavc 54.59.100 / 54.28.0
  251 #define SSR_USE_AVCODEC_FREE_FRAME                 TEST_AV_VERSION(LIBAVCODEC, 54, 59, 54, 28)
  252 // AV_CODEC_ID_* instead of CODEC_ID_*: lavc 54.51.100 / 54.25.0
  253 #define SSR_USE_AV_CODEC_ID                        TEST_AV_VERSION(LIBAVCODEC, 54, 51, 54, 25)
  254 // AVFrame::channels: lavc 54.46.100 / ???
  255 #define SSR_USE_AVFRAME_CHANNELS                   TEST_AV_VERSION(LIBAVCODEC, 54, 46, 999, 999)
  256 // AVFrame::sample_rate: lavc 54.20.100 / 54.13.0
  257 #define SSR_USE_AVFRAME_SAMPLE_RATE                TEST_AV_VERSION(LIBAVCODEC, 54, 20, 54, 13)
  258 // av_codec_is_encoder: lavc 54.8.100 / 54.7.0
  259 #define SSR_USE_AV_CODEC_IS_ENCODER                TEST_AV_VERSION(LIBAVCODEC, 54, 8, 54, 7)
  260 // avcodec_encode_video2: lavc 54.2.100 / 54.1.0
  261 #define SSR_USE_AVCODEC_ENCODE_VIDEO2              TEST_AV_VERSION(LIBAVCODEC, 54, 2, 54, 1)
  262 // avcodec_encode_audio2: lavc 53.56.105 / 53.34.0
  263 #define SSR_USE_AVCODEC_ENCODE_AUDIO2              TEST_AV_VERSION(LIBAVCODEC, 53, 56, 53, 34)
  264 // AVFrame::nb_samples, AVFrame::extended_data and avcodec_decode_audio4: lavc 53.40.0 / 53.25.0
  265 #define SSR_USE_AVFRAME_NB_SAMPLES                 TEST_AV_VERSION(LIBAVCODEC, 53, 40, 53, 25)
  266 #define SSR_USE_AVFRAME_EXTENDED_DATA              SSR_USE_AVFRAME_NB_SAMPLES
  267 #define SSR_USE_AVCODEC_DECODE_AUDIO4              SSR_USE_AVFRAME_NB_SAMPLES
  268 // the 'preset' private option: lavc 53.8 / 53.8
  269 // - ffmpeg: missing, commit: http://git.videolan.org/?p=ffmpeg.git;a=commit;h=07a227b432e49f4c0f35bbef48009f4d8438b32e
  270 // - libav: missing, commit: https://git.libav.org/?p=libav.git;a=commit;h=07a227b432e49f4c0f35bbef48009f4d8438b32e
  271 #define SSR_USE_AVCODEC_PRIVATE_PRESET             TEST_AV_VERSION(LIBAVCODEC, 53, 8, 53, 8)
  272 // the 'crf' private option: lavc 53.8 / 53.8
  273 // - ffmpeg: missing, commit: http://git.videolan.org/?p=ffmpeg.git;a=commit;h=d5dc8cc2974c816ba964692b75c9f17f40830414
  274 // - libav: missing, commit: https://git.libav.org/?p=libav.git;a=commit;h=d5dc8cc2974c816ba964692b75c9f17f40830414
  275 #define SSR_USE_AVCODEC_PRIVATE_CRF                TEST_AV_VERSION(LIBAVCODEC, 53, 8, 53, 8)
  276 // AVFrame::format: lavc 53.5.0 / 53.31.0
  277 #define SSR_USE_AVFRAME_FORMAT                     TEST_AV_VERSION(LIBAVCODEC, 53, 5, 53, 31)
  278 // AVFrame::width, AVFrame::height: lavc 53.4.0 / 53.31.0
  279 #define SSR_USE_AVFRAME_WIDTH_HEIGHT               TEST_AV_VERSION(LIBAVCODEC, 53, 4, 53, 31)
  280 // AVFrame::sample_aspect_ratio: lavc 53.3.0 / 53.31.0
  281 #define SSR_USE_AVFRAME_SAR                        TEST_AV_VERSION(LIBAVCODEC, 53, 3, 53, 31)
  282 
  283 // AV_PIX_FMT_* instead of PIX_FMT_*: lavu 51.74.100 / 51.42.0
  284 #define SSR_USE_AV_PIX_FMT                         TEST_AV_VERSION(LIBAVUTIL, 51, 74, 51, 42)
  285 // planar sample formats: lavu 51.27.0 / 51.17.0
  286 #define SSR_USE_AVUTIL_PLANAR_SAMPLE_FMT           TEST_AV_VERSION(LIBAVUTIL, 51, 27, 51, 17)
  287 
  288 // exception thrown when errors occur in external libraries
  289 class LibavException : public std::exception {
  290 public:
  291     inline virtual const char* what() const throw() override {
  292         return "LibavException";
  293     }
  294 };
  295 class ResamplerException : public std::exception {
  296 public:
  297     inline virtual const char* what() const throw() override {
  298         return "ResamplerException";
  299     }
  300 };
  301 class X11Exception : public std::exception {
  302 public:
  303     inline virtual const char* what() const throw() override {
  304         return "X11Exception";
  305     }
  306 };
  307 class GLInjectException : public std::exception {
  308 public:
  309     inline virtual const char* what() const throw() override {
  310         return "GLInjectException";
  311     }
  312 };
  313 class SSRStreamException : public std::exception {
  314 public:
  315     inline virtual const char* what() const throw() override {
  316         return "SSRStreamException";
  317     }
  318 };
  319 #if SSR_USE_ALSA
  320 class ALSAException : public std::exception {
  321 public:
  322     inline virtual const char* what() const throw() override {
  323         return "ALSAException";
  324     }
  325 };
  326 #endif
  327 #if SSR_USE_PULSEAUDIO
  328 class PulseAudioException : public std::exception {
  329 public:
  330     inline virtual const char* what() const throw() override {
  331         return "PulseAudioException";
  332     }
  333 };
  334 #endif
  335 #if SSR_USE_JACK
  336 class JACKException : public std::exception {
  337 public:
  338     inline virtual const char* what() const throw() override {
  339         return "JACKException";
  340     }
  341 };
  342 #endif
  343 
  344 // simple function to do 16-byte alignment
  345 inline size_t grow_align16(size_t size) {
  346     return (size_t) (size + 15) & ~((size_t) 15);
  347 }
  348 
  349 // high resolution timer
  350 inline int64_t hrt_time_micro() {
  351     timespec ts;
  352     clock_gettime(CLOCK_MONOTONIC, &ts);
  353     return (uint64_t) ts.tv_sec * (uint64_t) 1000000 + (uint64_t) (ts.tv_nsec / 1000);
  354 }
  355 
  356 // Returns the name of the user.
  357 inline std::string GetUserName() {
  358     std::vector<char> buf(std::max((long) 16384, sysconf(_SC_GETPW_R_SIZE_MAX)));
  359     passwd pwd, *result = NULL;
  360     if(getpwuid_r(geteuid(), &pwd, buf.data(), buf.size(), &result) == 0 && result != NULL)
  361         return std::string(result->pw_name);
  362     return "unknownuser";
  363 }
  364 
  365 template<typename T>
  366 inline T positive_mod(T x, T y) {
  367     T z = x % y;
  368     return (z < 0)? z + y : z;
  369 }
  370 
  371 template<typename T>
  372 inline T clamp(T v, T lo, T hi) {
  373     assert(lo <= hi);
  374     if(v < lo)
  375         return lo;
  376     if(v > hi)
  377         return hi;
  378     return v;
  379 }
  380 template<> inline float clamp<float>(float v, float lo, float hi) {
  381     assert(lo <= hi);
  382     return fmin(fmax(v, lo), hi);
  383 }
  384 template<> inline double clamp<double>(double v, double lo, double hi) {
  385     assert(lo <= hi);
  386     return fmin(fmax(v, lo), hi);
  387 }
  388 
  389 // Generic number-to-string conversion and vice versa
  390 // Unlike the standard functions, these are locale-independent, and the functions never throw exceptions.
  391 template<typename T>
  392 inline std::string NumToString(T number) {
  393     std::ostringstream ss;
  394     ss << number;
  395     return ss.str();
  396 }
  397 template<typename T>
  398 inline bool StringToNum(const std::string& str, T* number) {
  399     std::istringstream ss(str);
  400     ss >> *number;
  401     return !ss.fail();
  402 }
  403 
  404 // convert weird types from libav/ffmpeg to doubles
  405 inline double ToDouble(const AVRational& r) {
  406     return (double) r.num / (double) r.den;
  407 }
  408 
  409 inline void GroupEnabled(std::initializer_list<QAction*> actions, bool enabled) {
  410     for(QAction *a : actions) {
  411         a->setEnabled(enabled);
  412     }
  413 }
  414 inline void GroupEnabled(std::initializer_list<QWidget*> widgets, bool enabled) {
  415     for(QWidget *w : widgets) {
  416         w->setEnabled(enabled);
  417     }
  418 }
  419 inline void GroupVisible(std::initializer_list<QWidget*> widgets, bool visible) {
  420     for(QWidget *w : widgets) {
  421         w->setVisible(visible);
  422     }
  423 }
  424 inline void MultiGroupVisible(std::initializer_list<std::pair<std::initializer_list<QWidget*>, bool> > conditions) {
  425     // Qt updates the layout every time something is made visible or invisible, so the order is important.
  426     // First hide everything that needs to be hidden, then show everything that needs to be shown.
  427     // If the order is wrong, Qt will make the widget larger than necessary.
  428     for(auto &c : conditions) {
  429         if(!c.second)
  430             GroupVisible(c.first, false);
  431     }
  432     for(auto &c : conditions) {
  433         if(c.second)
  434             GroupVisible(c.first, true);
  435     }
  436 }
  437 
  438 #endif // GLOBAL_H