Skip to content

Commit

Permalink
windows: PlayerCreateHWND impl & win32 window creation on another thread
Browse files Browse the repository at this point in the history
- creating window using package:win32 on another Isolate seemed impossible to close. Sending WM_CLOSE freezed everything.
- now native window is created through windows-specific platform channel implementation.
- another important thing that this fixed is hot-reload.
  • Loading branch information
alexmercerind committed May 5, 2022
1 parent 496d1d5 commit 12caada
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 12 deletions.
1 change: 1 addition & 0 deletions windows/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ add_subdirectory(../core "${CMAKE_BINARY_DIR}/${PROJECT_NAME}_core")
add_library("${PLUGIN_NAME}" SHARED
"dart_vlc_plugin.cc"
"video_outlet.cc"
"win32_window.cc"
)

apply_standard_settings("${PLUGIN_NAME}")
Expand Down
23 changes: 12 additions & 11 deletions windows/dart_vlc_plugin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
#include <unordered_map>

#include "core.h"
#include "video_outlet.h"
#include "include/dart_vlc/video_outlet.h"
#include "include/dart_vlc/win32_window.h"

namespace {

Expand Down Expand Up @@ -69,8 +70,6 @@ DartVlcPlugin::DartVlcPlugin(
: channel_(std::move(channel)), texture_registrar_(texture_registrar) {}

DartVlcPlugin::~DartVlcPlugin() {
// Clean up unreleased players when the flutter engine is destroyed to avoid
// crashes.
for (const auto& [player_id, outlet] : outlets_) {
auto player = g_players->Get(player_id);
player->SetVideoFrameCallback(nullptr);
Expand All @@ -86,7 +85,6 @@ void DartVlcPlugin::HandleMethodCall(
std::get<flutter::EncodableMap>(*method_call.arguments());
int32_t player_id =
std::get<int>(arguments[flutter::EncodableValue("playerId")]);

auto [it, added] = outlets_.try_emplace(player_id, nullptr);
if (added) {
it->second = std::make_unique<VideoOutlet>(texture_registrar_);
Expand All @@ -99,24 +97,27 @@ void DartVlcPlugin::HandleMethodCall(
}

return result->Success(flutter::EncodableValue(it->second->texture_id()));

} else if (method_call.method_name() == "PlayerUnregisterTexture") {
flutter::EncodableMap arguments =
std::get<flutter::EncodableMap>(*method_call.arguments());
int player_id =
auto player_id =
std::get<int>(arguments[flutter::EncodableValue("playerId")]);
if (outlets_.find(player_id) == outlets_.end()) {
return result->Error("-2", "Texture was not found.");
}

// The callback must be unregistered
// before destroying the outlet.
auto player = g_players->Get(player_id);
player->SetVideoFrameCallback(nullptr);

outlets_.erase(player_id);

result->Success(flutter::EncodableValue(nullptr));
} else if (method_call.method_name() == "PlayerCreateHWND") {
flutter::EncodableMap arguments =
std::get<flutter::EncodableMap>(*method_call.arguments());
auto player_id =
std::get<int>(arguments[flutter::EncodableValue("playerId")]);
auto player = g_players->Get(player_id);
auto window = CreateWin32Window();
player->SetHWND(reinterpret_cast<int64_t>(window));
result->Success(flutter::EncodableValue(reinterpret_cast<int64_t>(window)));
} else {
result->NotImplemented();
}
Expand Down
File renamed without changes.
34 changes: 34 additions & 0 deletions windows/include/dart_vlc/win32_window.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// This file is a part of dart_vlc (https://github.com/alexmercerind/dart_vlc)
//
// Copyright (C) 2021-2022 Hitesh Kumar Saini <[email protected]>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

#ifndef WIN32_WINDOW_H_
#define WIN32_WINDOW_H_

#ifndef UNICODE
#define UNICODE
#endif

#include <Windows.h>
#include <stdint.h>

HWND CreateWin32Window();

LRESULT CALLBACK Win32WindowProc(HWND window, UINT message, WPARAM wparam,
LPARAM lparam);

#endif
2 changes: 1 addition & 1 deletion windows/video_outlet.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
// along with this program; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

#include "video_outlet.h"
#include "include/dart_vlc/video_outlet.h"

VideoOutlet::VideoOutlet(flutter::TextureRegistrar* texture_registrar)
: texture_registrar_(texture_registrar) {
Expand Down
72 changes: 72 additions & 0 deletions windows/win32_window.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// This file is a part of dart_vlc (https://github.com/alexmercerind/dart_vlc)
//
// Copyright (C) 2021-2022 Hitesh Kumar Saini <[email protected]>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "include/dart_vlc/win32_window.h"

#include <future>
#include <random>
#include <string>
#include <thread>

constexpr auto kWindowClassName = L"DART_VLC_WINDOW";

HWND CreateWin32Window() {
std::promise<HWND> window_promise;
std::thread([&]() {
auto startup_info = STARTUPINFO{};
::GetStartupInfo(&startup_info);
auto instance = ::GetModuleHandle(nullptr);
auto window_class = WNDCLASS{};
window_class.lpszClassName = kWindowClassName;
window_class.style = CS_HREDRAW | CS_VREDRAW;
window_class.lpfnWndProc = Win32WindowProc;
window_class.cbClsExtra = 0;
window_class.cbWndExtra = 0;
window_class.hInstance = instance;
window_class.hIcon = ::LoadIcon(nullptr, IDI_APPLICATION);
window_class.hCursor = ::LoadCursor(nullptr, IDC_ARROW);
window_class.hbrBackground =
static_cast<HBRUSH>(::CreateSolidBrush(RGB(0, 0, 0)));
::RegisterClass(&window_class);
std::random_device random_device;
std::mt19937 range(random_device());
std::uniform_int_distribution<int> uniform(0, INT32_MAX);
HWND window = CreateWindowEx(
0, kWindowClassName,
(L"dart_vlc.instance." + std::to_wstring(uniform(range))).c_str(),
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, NULL, NULL, instance, nullptr);
window_promise.set_value(window);
MSG msg;
while (::GetMessage(&msg, window, 0, 0)) {
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}).detach();
return window_promise.get_future().get();
}

LRESULT CALLBACK Win32WindowProc(HWND window, UINT message, WPARAM wparam,
LPARAM lparam) {
switch (message) {
case WM_DESTROY: {
::PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(window, message, wparam, lparam);
}

0 comments on commit 12caada

Please sign in to comment.