Sfoglia il codice sorgente

UI: Add media/image file drop support

jp9000 9 anni fa
parent
commit
eb1fecdd34

+ 1 - 0
UI/CMakeLists.txt

@@ -112,6 +112,7 @@ set(obs_SOURCES
 	window-basic-source-select.cpp
 	window-basic-main-scene-collections.cpp
 	window-basic-main-transitions.cpp
+	window-basic-main-dropfiles.cpp
 	window-basic-main-profiles.cpp
 	window-license-agreement.cpp
 	window-basic-status-bar.cpp

+ 8 - 0
UI/platform-windows.cpp

@@ -230,3 +230,11 @@ void SetProcessPriority(const char *priority)
 	else if (strcmp(priority, "Idle") == 0)
 		SetPriorityClass(GetCurrentProcess(), IDLE_PRIORITY_CLASS);
 }
+
+void SetWin32DropStyle(QWidget *window)
+{
+	HWND hwnd = (HWND)window->winId();
+	LONG_PTR ex_style = GetWindowLongPtr(hwnd, GWL_EXSTYLE);
+	ex_style |= WS_EX_ACCEPTFILES;
+	SetWindowLongPtr(hwnd, GWL_EXSTYLE, ex_style);
+}

+ 1 - 0
UI/platform.hpp

@@ -52,6 +52,7 @@ void SetAlwaysOnTop(QWidget *window, bool enable);
 uint32_t GetWindowsVersion();
 void SetAeroEnabled(bool enable);
 void SetProcessPriority(const char *priority);
+void SetWin32DropStyle(QWidget *window);
 #endif
 
 #ifdef __APPLE__

+ 142 - 0
UI/window-basic-main-dropfiles.cpp

@@ -0,0 +1,142 @@
+#include <QDragEnterEvent>
+#include <QDragLeaveEvent>
+#include <QDragMoveEvent>
+#include <QDropEvent>
+#include <QFileInfo>
+#include <QMimeData>
+#include <string>
+
+#include "window-basic-main.hpp"
+#include "qt-wrappers.hpp"
+
+using namespace std;
+
+static const char *imageExtensions[] = {
+	"bmp", "tga", "png", "jpg", "jpeg", "gif", nullptr
+};
+
+static const char *mediaExtensions[] = {
+	"3ga", "669", "a52", "aac", "ac3", "adt", "adts", "aif", "aifc",
+	"aiff", "amb", "amr", "aob", "ape", "au", "awb", "caf", "dts",
+	"flac", "it", "kar", "m4a", "m4b", "m4p", "m5p", "mid", "mka",
+	"mlp", "mod", "mpa", "mp1", "mp2", "mp3", "mpc", "mpga", "mus",
+	"oga", "ogg", "oma", "opus", "qcp", "ra", "rmi", "s3m", "sid",
+	"spx", "tak", "thd", "tta", "voc", "vqf", "w64", "wav", "wma",
+	"wv", "xa", "xm" "3g2", "3gp", "3gp2", "3gpp", "amv", "asf", "avi",
+	"bik", "crf", "divx", "drc", "dv", "evo", "f4v", "flv", "gvi",
+	"gxf", "iso", "m1v", "m2v", "m2t", "m2ts", "m4v", "mkv", "mov",
+	"mp2", "mp2v", "mp4", "mp4v", "mpe", "mpeg", "mpeg1", "mpeg2",
+	"mpeg4", "mpg", "mpv2", "mts", "mtv", "mxf", "mxg", "nsv", "nuv",
+	"ogg", "ogm", "ogv", "ogx", "ps", "rec", "rm", "rmvb", "rpl", "thp",
+	"tod", "ts", "tts", "txd", "vob", "vro", "webm", "wm", "wmv", "wtv",
+	nullptr
+};
+
+static string GenerateSourceName(const char *base)
+{
+	string name;
+	int inc = 0;
+
+	for (;; inc++) {
+		name = base;
+
+		if (inc) {
+			name += " (";
+			name += to_string(inc+1);
+			name += ")";
+		}
+
+		obs_source_t *source = obs_get_source_by_name(name.c_str());
+		if (!source)
+			return name;
+	}
+}
+
+void OBSBasic::AddDropSource(const char *file, bool image)
+{
+	OBSBasic *main = reinterpret_cast<OBSBasic*>(App()->GetMainWindow());
+	obs_data_t *settings = obs_data_create();
+	obs_source_t *source = nullptr;
+	const char *type = nullptr;
+
+	if (image) {
+		obs_data_set_string(settings, "file", file);
+		type = "image_source";
+	} else {
+		obs_data_set_string(settings, "local_file", file);
+		type = "ffmpeg_source";
+	}
+
+	const char *name = obs_source_get_display_name(type);
+	source = obs_source_create(type, GenerateSourceName(name).c_str(),
+			settings, nullptr);
+	if (source) {
+		OBSScene scene = main->GetCurrentScene();
+		obs_scene_add(scene, source);
+		obs_source_release(source);
+	}
+
+	obs_data_release(settings);
+}
+
+void OBSBasic::dragEnterEvent(QDragEnterEvent *event)
+{
+	event->acceptProposedAction();
+}
+
+void OBSBasic::dragLeaveEvent(QDragLeaveEvent *event)
+{
+	event->accept();
+}
+
+void OBSBasic::dragMoveEvent(QDragMoveEvent *event)
+{
+	event->acceptProposedAction();
+}
+
+void OBSBasic::dropEvent(QDropEvent *event)
+{
+	const QMimeData* mimeData = event->mimeData();
+
+	if (mimeData->hasUrls()) {
+		QList<QUrl> urls = mimeData->urls();
+
+		for (int i = 0; i < urls.size() && i < 5; i++) {
+			QString file = urls.at(i).toLocalFile();
+			QFileInfo fileInfo(file);
+
+			if (!fileInfo.exists())
+				continue;
+
+			QString suffixQStr = fileInfo.suffix();
+			QByteArray suffixArray = suffixQStr.toUtf8();
+			const char *suffix = suffixArray.constData();
+			bool found = false;
+
+			const char **cmp = imageExtensions;
+			while (*cmp) {
+				if (strcmp(*cmp, suffix) == 0) {
+					AddDropSource(QT_TO_UTF8(file), true);
+					found = true;
+					break;
+				}
+
+				cmp++;
+			}
+
+			if (found)
+				continue;
+
+			cmp = mediaExtensions;
+			while (*cmp) {
+				if (strcmp(*cmp, suffix) == 0) {
+					AddDropSource(QT_TO_UTF8(file), false);
+					break;
+				}
+
+				cmp++;
+			}
+		}
+	}
+}
+

+ 3 - 0
UI/window-basic-main.cpp

@@ -120,6 +120,8 @@ OBSBasic::OBSBasic(QWidget *parent)
 	: OBSMainWindow  (parent),
 	  ui             (new Ui::OBSBasic)
 {
+	setAcceptDrops(true);
+
 	ui->setupUi(this);
 	ui->previewDisabledLabel->setVisible(false);
 
@@ -1166,6 +1168,7 @@ void OBSBasic::OBSInit()
 	connect(ui->preview, &OBSQTDisplay::DisplayCreated, addDisplay);
 
 #ifdef _WIN32
+	SetWin32DropStyle(this);
 	show();
 #endif
 

+ 6 - 0
UI/window-basic-main.hpp

@@ -299,6 +299,12 @@ private:
 	inline void OnActivate();
 	inline void OnDeactivate();
 
+	void AddDropSource(const char *file, bool image);
+	void dragEnterEvent(QDragEnterEvent *event) override;
+	void dragLeaveEvent(QDragLeaveEvent *event) override;
+	void dragMoveEvent(QDragMoveEvent *event) override;
+	void dropEvent(QDropEvent *event) override;
+
 public slots:
 	void StartStreaming();
 	void StopStreaming();