diff --git a/src/core.cpp b/src/core.cpp
index 5d738ec9f..b17125cbb 100644
--- a/src/core.cpp
+++ b/src/core.cpp
@@ -1741,18 +1741,16 @@ void Core::startMplayer( QString file, double seek ) {
         */
 		#endif
 		#ifdef Q_OS_MACX
-		if (pref->use_mplayer_window || display_screen != 0) {
-			if (proc->isMPlayer()) proc->setOption("vo", "gl,"); else proc->setOption("vo", "gpu,");
-		} else {
-			#ifdef USE_SHM
-			proc->setOption("vo", "shm,");
-			#else
+		if (proc->isMPlayer()) {
 			#ifdef USE_COREVIDEO_BUFFER
-			if (proc->isMPlayer()) {
-				proc->setOption("vo", "corevideo,");
-			}
+			proc->setOption("vo", "corevideo,");
+			#else
+			proc->setOption("vo", "gl,");
 			#endif
-			#endif // USE_SHM
+		} else {
+			// For mpv on macOS: libmpv is designed for embedding and supports WID
+			// If libmpv is not available, gpu/cocoa will open a separate window
+			proc->setOption("vo", "libmpv,gpu,");
 		}
 		#endif // Q_OS_MACX
 	}
@@ -1859,10 +1857,8 @@ void Core::startMplayer( QString file, double seek ) {
 		#define WINIDFROMHWND(hwnd) ( ( hwnd ) - 0x80000000UL )
 		proc->setOption("wid", QString::number( WINIDFROMHWND( (int) mplayerwindow->videoLayer()->winId() ) ));
 		#else
-		#ifndef Q_OS_MACX
 		proc->setOption("wid", QString::number( (qint64) mplayerwindow->videoLayer()->winId() ) );
 		#endif
-		#endif
 
 #if USE_COLORKEY
 		#if defined(Q_OS_WIN) || defined(Q_OS_OS2)
diff --git a/src/main.cpp b/src/main.cpp
index 0dbcaf614..9aa9aa001 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -20,7 +20,7 @@
 #include "smplayer.h"
 
 #include <QDir>
-#ifdef USE_GL_WINDOW
+#if defined(USE_GL_WINDOW) && QT_VERSION >= 0x050000
 #include <QSurfaceFormat>
 #endif
 
@@ -76,7 +76,7 @@ int main( int argc, char ** argv )
 
 	MyApplication a( "smplayer", argc, argv );
 
-#ifdef USE_GL_WINDOW
+#if defined(USE_GL_WINDOW) && QT_VERSION >= 0x050000
 	QSurfaceFormat fmt;
 	fmt.setVersion( 3, 2 );
 	fmt.setProfile( QSurfaceFormat::CoreProfile );
diff --git a/src/mconnection.mm b/src/mconnection.mm
index bf232bab2..a229acfd1 100644
--- a/src/mconnection.mm
+++ b/src/mconnection.mm
@@ -53,7 +53,11 @@ MConnection::MConnection(ConnectionCV * w, const QString & name) {
 }
 
 void MConnection::startConnection() {
+#if QT_VERSION >= 0x050000
 	NSString * name = buffer_name.toNSString();
+#else
+	NSString * name = [NSString stringWithUTF8String:buffer_name.toUtf8().constData()];
+#endif
 	mpc = [[MPlayerConnection alloc] initWithName:name];
 }
 
diff --git a/src/myapplication.h b/src/myapplication.h
index 2010796cf..423fc8edb 100644
--- a/src/myapplication.h
+++ b/src/myapplication.h
@@ -20,6 +20,7 @@
 #define MYAPPLICATION_H
 
 #include <QtGlobal>
+#include <QStringList>
 
 #ifdef SINGLE_INSTANCE
 #include "QtSingleApplication"
diff --git a/src/openglrenderer.cpp b/src/openglrenderer.cpp
index 6aa0fced2..ccbe6ec6b 100644
--- a/src/openglrenderer.cpp
+++ b/src/openglrenderer.cpp
@@ -16,29 +16,40 @@
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 
+#define GL_SILENCE_DEPRECATION
 #include "openglrenderer.h"
 
-#include <QGLShaderProgram>
-#include <QRegularExpression>
+#if QT_VERSION >= 0x050000
+  #include <QRegularExpression>
+  #include <QOpenGLContext>
+#endif
 #include <QFile>
 #include <QDebug>
 
 OpenGLRenderer::OpenGLRenderer(QObject * parent)
 	: QObject(parent)
+#if QT_VERSION >= 0x050000
 	, vertex_buffer(QOpenGLBuffer::VertexBuffer)
+#else
+	, vertex_buffer(QGLBuffer::VertexBuffer)
+#endif
 	, vertex_shader(0)
 	, fragment_shader(0)
 	, current_format(0)
 	, current_colorspace(ConnectionBase::CSP_BT_709)
 {
+#if QT_VERSION >= 0x050000
 	//glsl_version = "130";
 	glsl_version = "330";
+#else
+	glsl_version = "120";
+#endif
 
 	for (int n = 0; n < 3; n++) {
 		textures[n] = 0;
 	}
 
-	GLfloat matrix[] = {
+	double matrix[] = {
 		1.660497, -0.587657, -0.072840,
 		-0.124547, 1.132895, -0.008348,
 		-0.018154, -0.100597, 1.118751
@@ -82,7 +93,11 @@ void OpenGLRenderer::createFragmentShader() {
 	int attribute_vertex;
 	int attribute_texture;
 
+#if QT_VERSION >= 0x050000
 	fragment_shader = new QOpenGLShader(QOpenGLShader::Fragment, this);
+#else
+	fragment_shader = new QGLShader(QGLShader::Fragment, this);
+#endif
 
 	QString code;
 
@@ -120,8 +135,12 @@ void OpenGLRenderer::createFragmentShader() {
 
 	for (int n = 0; n < 3; n++) {
 		if (textures[n] == 0) {
+#if QT_VERSION >= 0x050000
 			textures[n] = new QOpenGLTexture(QOpenGLTexture::Target2D);
 			textures[n]->create();
+#else
+			glGenTextures(1, &textures[n]);
+#endif
 		}
 	}
 }
@@ -131,16 +150,18 @@ void OpenGLRenderer::initializeGL(int window_width, int window_height) {
 	Q_UNUSED(window_height);
 
 	qDebug("OpenGLRenderer::initializeGL");
+#if QT_VERSION >= 0x050000
 	initializeOpenGLFunctions();
 
 	if (QOpenGLContext::currentContext()->isOpenGLES()) {
 		glsl_version = "300 es";
 	}
+#endif
 
 	glEnable(GL_TEXTURE_2D);
 	glDisable(GL_DEPTH_TEST);
 
-	static const GLfloat coordinates[2][4][2]{
+	static const GLfloat coordinates[2][4][2] = {
 		{
 			/* Vertex coordinates */
 			{ -1.0f, -1.0f },
@@ -162,7 +183,11 @@ void OpenGLRenderer::initializeGL(int window_width, int window_height) {
 	vertex_buffer.allocate(coordinates, sizeof(coordinates));
 
 	/* Create Vertex Shader */
+#if QT_VERSION >= 0x050000
 	vertex_shader = new QOpenGLShader(QOpenGLShader::Vertex, this);
+#else
+	vertex_shader = new QGLShader(QGLShader::Vertex, this);
+#endif
 	QString code = QString(
 		"in vec4 vertexIn; \n"
 		"in vec2 textureIn; \n"
@@ -177,11 +202,18 @@ void OpenGLRenderer::initializeGL(int window_width, int window_height) {
 	}
 	program.addShader(vertex_shader);
 
+#if QT_VERSION >= 0x050000
 	if (vao.create()) vao.bind();
+#endif
 }
 
+#if QT_VERSION >= 0x050000
 void OpenGLRenderer::configureTexture(QOpenGLTexture &texture) {
 	glBindTexture(GL_TEXTURE_2D, texture.textureId());
+#else
+void OpenGLRenderer::configureTexture(GLuint texture) {
+	glBindTexture(GL_TEXTURE_2D, texture);
+#endif
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@@ -205,7 +237,11 @@ void OpenGLRenderer::paintGL(int window_width, int window_height, int image_widt
 	// Render
 	if (current_format == ConnectionBase::YUY2 || current_format == ConnectionBase::UYVY) {
 		glActiveTexture(GL_TEXTURE0);
+#if QT_VERSION >= 0x050000
 		configureTexture(*textures[0]);
+#else
+		configureTexture(textures[0]);
+#endif
 
 		glTexImage2D(GL_TEXTURE_2D,
 			     0,
@@ -222,7 +258,11 @@ void OpenGLRenderer::paintGL(int window_width, int window_height, int image_widt
 	else
 	if (current_format == ConnectionBase::RGB24) {
 		glActiveTexture(GL_TEXTURE0);
+#if QT_VERSION >= 0x050000
 		configureTexture(*textures[0]);
+#else
+		configureTexture(textures[0]);
+#endif
 		glTexImage2D(GL_TEXTURE_2D,
 			     0,
 			     GL_RGB,
@@ -237,10 +277,14 @@ void OpenGLRenderer::paintGL(int window_width, int window_height, int image_widt
 	else
 	if (current_format == ConnectionBase::RGB16) {
 		glActiveTexture(GL_TEXTURE0);
+#if QT_VERSION >= 0x050000
 		configureTexture(*textures[0]);
+#else
+		configureTexture(textures[0]);
+#endif
 		glTexImage2D(GL_TEXTURE_2D,
 			     0,
-			     GL_RGB565,
+			     GL_RGB,
 			     image_width,
 			     image_height,
 			     0,
@@ -259,7 +303,11 @@ void OpenGLRenderer::paintGL(int window_width, int window_height, int image_widt
 
 		/* Activate texture Y */
 		glActiveTexture(GL_TEXTURE0);
+#if QT_VERSION >= 0x050000
 		configureTexture(*textures[0]);
+#else
+		configureTexture(textures[0]);
+#endif
 		glTexImage2D(GL_TEXTURE_2D,
 			     0,
 			     GL_RED,
@@ -272,7 +320,11 @@ void OpenGLRenderer::paintGL(int window_width, int window_height, int image_widt
 
 		/* Activate texture U */
 		glActiveTexture(GL_TEXTURE1);
+#if QT_VERSION >= 0x050000
 		configureTexture(*textures[1]);
+#else
+		configureTexture(textures[1]);
+#endif
 		glTexImage2D(GL_TEXTURE_2D,
 			     0,
 			     GL_RED,
@@ -285,7 +337,11 @@ void OpenGLRenderer::paintGL(int window_width, int window_height, int image_widt
 
 		/* Activate texture V */
 		glActiveTexture(GL_TEXTURE2);
+#if QT_VERSION >= 0x050000
 		configureTexture(*textures[2]);
+#else
+		configureTexture(textures[2]);
+#endif
 		glTexImage2D(GL_TEXTURE_2D,
 			     0,
 			     GL_RED,
@@ -489,9 +545,20 @@ QString OpenGLRenderer::glslCode(QString code) {
 		code = code.replace("in vec2 textureOut", "varying vec2 textureOut");
 		code = code.replace("fragColor", "gl_FragColor");
 		code = code.replace("out ", "varying ");
+#if QT_VERSION >= 0x050000
 		QRegularExpression rx("^in ");
 		rx.setPatternOptions(QRegularExpression::MultilineOption);
 		code = code.replace(rx, "attribute ");
+#else
+		// For Qt4, process line by line
+		QStringList lines = code.split('\n');
+		for (int i = 0; i < lines.size(); ++i) {
+			if (lines[i].startsWith("in ")) {
+				lines[i].replace(0, 3, "attribute ");
+			}
+		}
+		code = lines.join("\n");
+#endif
 		code = code.replace("texture(", "texture2D(");
 		//qDebug("OpenGLRenderer::glslCode: code OUT: %s", code.toLatin1().constData());
 	}
diff --git a/src/openglrenderer.h b/src/openglrenderer.h
index d26dd67ae..5ed44e7da 100644
--- a/src/openglrenderer.h
+++ b/src/openglrenderer.h
@@ -21,14 +21,29 @@
 
 #include "connectionbase.h"
 
-#include <QOpenGLBuffer>
-#include <QOpenGLFunctions>
-#include <QOpenGLShader>
-#include <QOpenGLShaderProgram>
-#include <QOpenGLTexture>
-#include <QOpenGLVertexArrayObject>
-
-class OpenGLRenderer : public QObject, protected QOpenGLFunctions
+#if QT_VERSION >= 0x050000
+  #include <QOpenGLBuffer>
+  #include <QOpenGLFunctions>
+  #include <QOpenGLShader>
+  #include <QOpenGLShaderProgram>
+  #include <QOpenGLTexture>
+  #include <QOpenGLVertexArrayObject>
+  #define GL_BUFFER_CLASS QOpenGLBuffer
+  #define GL_SHADER_CLASS QOpenGLShader
+  #define GL_SHADER_PROGRAM_CLASS QOpenGLShaderProgram
+#else
+  #include <QGLBuffer>
+  #include <QGLShader>
+  #include <QGLShaderProgram>
+  #define GL_BUFFER_CLASS QGLBuffer
+  #define GL_SHADER_CLASS QGLShader
+  #define GL_SHADER_PROGRAM_CLASS QGLShaderProgram
+#endif
+
+class OpenGLRenderer : public QObject
+#if QT_VERSION >= 0x050000
+  , protected QOpenGLFunctions
+#endif
 {
 	Q_OBJECT
 
@@ -50,7 +65,11 @@ public:
 	virtual void resizeGL(int w, int h);
 
 protected:
+#if QT_VERSION >= 0x050000
 	void configureTexture(QOpenGLTexture &texture);
+#else
+	void configureTexture(GLuint texture);
+#endif
 	void createFragmentShader();
 
 	QString rgbShader();
@@ -62,14 +81,20 @@ protected:
 	QString glslCode(QString code);
 	QString glsl_version;
 
-	QOpenGLBuffer vertex_buffer;
+	GL_BUFFER_CLASS vertex_buffer;
 
+#if QT_VERSION >= 0x050000
 	QOpenGLTexture * textures[3];
+#else
+	GLuint textures[3];
+#endif
 
-	QOpenGLShader * vertex_shader;
-	QOpenGLShader * fragment_shader;
-	QOpenGLShaderProgram program;
+	GL_SHADER_CLASS * vertex_shader;
+	GL_SHADER_CLASS * fragment_shader;
+	GL_SHADER_PROGRAM_CLASS program;
+#if QT_VERSION >= 0x050000
 	QOpenGLVertexArrayObject vao;
+#endif
 
 	GLuint textureUniformU;
 	GLuint textureUniformV;
diff --git a/src/smplayer.pro b/src/smplayer.pro
index a996a34cc..f0e5740d7 100644
--- a/src/smplayer.pro
+++ b/src/smplayer.pro
@@ -620,6 +620,7 @@ contains( DEFINES, USE_POWERSAVING ) {
 	mac {
 		HEADERS += powersaving_mac.h
 		SOURCES += powersaving_mac.cpp
+		LIBS += -framework CoreFoundation -framework IOKit
 	}
 }
 
diff --git a/src/videolayer.cpp b/src/videolayer.cpp
index 35f4633a3..b5a146630 100644
--- a/src/videolayer.cpp
+++ b/src/videolayer.cpp
@@ -20,7 +20,11 @@
 #include <QDebug>
 
 VideoLayer::VideoLayer(QWidget* parent, Qt::WindowFlags f)
+#if defined(USE_GL_WINDOW) && (defined(USE_SHM) || defined(USE_COREVIDEO_BUFFER)) && QT_VERSION < 0x050400
+	: VIDEOLAYER_PARENT(parent, 0, f)  // QGLWidget requires shareWidget parameter
+#else
 	: VIDEOLAYER_PARENT(parent, f)
+#endif
 #if REPAINT_BACKGROUND_OPTION
 	, repaint_background(false)
 #endif
diff --git a/src/videolayer.h b/src/videolayer.h
index 280d94d3a..6d45591b1 100644
--- a/src/videolayer.h
+++ b/src/videolayer.h
@@ -21,9 +21,15 @@
 
 #include "config.h"
 
-#ifdef USE_GL_WINDOW
-  #include <QOpenGLWidget>
-  #define VIDEOLAYER_PARENT QOpenGLWidget
+// GL_WINDOW only makes sense with a way to get frames (SHM or COREVIDEO)
+#if defined(USE_GL_WINDOW) && (defined(USE_SHM) || defined(USE_COREVIDEO_BUFFER))
+  #if QT_VERSION >= 0x050400
+    #include <QOpenGLWidget>
+    #define VIDEOLAYER_PARENT QOpenGLWidget
+  #else
+    #include <QGLWidget>
+    #define VIDEOLAYER_PARENT QGLWidget
+  #endif
 #else
  #include <QWidget>
  #define VIDEOLAYER_PARENT QWidget
diff --git a/src/videolayerrender.cpp b/src/videolayerrender.cpp
index 9182897c9..d9f40c595 100644
--- a/src/videolayerrender.cpp
+++ b/src/videolayerrender.cpp
@@ -16,6 +16,7 @@
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 
+#define GL_SILENCE_DEPRECATION
 #include "videolayerrender.h"
 #include <QCoreApplication>
 #include <QTimer>
@@ -28,8 +29,12 @@
 #include <stdint.h>
 
 #ifdef USE_GL_WINDOW
-#include <QSurfaceFormat>
-#include "openglrenderer.h"
+  #if QT_VERSION >= 0x050000
+    #include <QSurfaceFormat>
+  #else
+    #include <QGLFormat>
+  #endif
+  #include "openglrenderer.h"
 #endif // USE_GL_WINDOW
 
 #include "connectionbase.h"
@@ -56,12 +61,19 @@ VideoLayerRender::VideoLayerRender(QWidget* parent, Qt::WindowFlags f)
 #endif
 {
 #ifdef USE_GL_WINDOW
-	QSurfaceFormat fmt = QSurfaceFormat::defaultFormat();
-	fmt.setSwapInterval(1);
-	fmt.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
-	//fmt.setColorSpace(QSurfaceFormat::sRGBColorSpace);
-	setFormat(fmt);
-	//qDebug() << "VideoLayerRender::VideoLayerRender: format:" << format();
+	#if QT_VERSION >= 0x050000
+		QSurfaceFormat fmt = QSurfaceFormat::defaultFormat();
+		fmt.setSwapInterval(1);
+		fmt.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
+		//fmt.setColorSpace(QSurfaceFormat::sRGBColorSpace);
+		setFormat(fmt);
+		//qDebug() << "VideoLayerRender::VideoLayerRender: format:" << format();
+	#else
+		QGLFormat fmt = QGLFormat::defaultFormat();
+		fmt.setSwapInterval(1);
+		fmt.setDoubleBuffer(true);
+		setFormat(fmt);
+	#endif
 
 	renderer = new OpenGLRenderer(this);
 	supported_formats << ConnectionBase::RGB24 << ConnectionBase::RGB16
@@ -252,7 +264,9 @@ void VideoLayerRender::resizeGL(int w, int h) {
 void VideoLayerRender::initializeGL() {
 	qDebug("VideoLayerRender::initializeGL: w: %d h: %d", width(), height());
 
-	initializeOpenGLFunctions();
+	#if QT_VERSION >= 0x050000
+		initializeOpenGLFunctions();
+	#endif
 	qDebug("VideoLayerRender::initializeGL: GL_VERSION: %s", glGetString(GL_VERSION));
 	qDebug("VideoLayerRender::initializeGL: GSLS version: %s", glGetString(GL_SHADING_LANGUAGE_VERSION));
 
diff --git a/src/videolayerrender.h b/src/videolayerrender.h
index bd7295cad..23f3e9a7f 100644
--- a/src/videolayerrender.h
+++ b/src/videolayerrender.h
@@ -27,8 +27,10 @@
 #define USE_YUV
 
 #ifdef USE_GL_WINDOW
-#include <QOpenGLFunctions>
-class OpenGLRenderer;
+  #if QT_VERSION >= 0x050000
+    #include <QOpenGLFunctions>
+  #endif
+  class OpenGLRenderer;
 #endif
 
 class QTimer;
@@ -37,7 +39,7 @@ class ConnectionBase;
 //#define COUNT_FPS
 
 class VideoLayerRender : public VideoLayer
-#ifdef USE_GL_WINDOW
+#if defined(USE_GL_WINDOW) && QT_VERSION >= 0x050000
 	, protected QOpenGLFunctions
 #endif
 {
