diff --git a/vav2/Vav2Player/Vav2Player/LogMessagePage.xaml b/vav2/Vav2Player/Vav2Player/LogMessagePage.xaml
index c823618..8c310bd 100644
--- a/vav2/Vav2Player/Vav2Player/LogMessagePage.xaml
+++ b/vav2/Vav2Player/Vav2Player/LogMessagePage.xaml
@@ -29,15 +29,25 @@
Foreground="White"
VerticalAlignment="Center"/>
-
+
+
+
+
+
@@ -53,15 +63,16 @@
+ CornerRadius="3"
+ Loaded="LogBorder_Loaded">
+ Foreground="Black"
+ x:Name="LogTextBlock"/>
diff --git a/vav2/Vav2Player/Vav2Player/LogMessagePage.xaml.cpp b/vav2/Vav2Player/Vav2Player/LogMessagePage.xaml.cpp
index 878c543..9bb9dec 100644
--- a/vav2/Vav2Player/Vav2Player/LogMessagePage.xaml.cpp
+++ b/vav2/Vav2Player/Vav2Player/LogMessagePage.xaml.cpp
@@ -8,6 +8,7 @@ using namespace winrt;
using namespace winrt::Microsoft::UI::Xaml;
using namespace winrt::Microsoft::UI::Xaml::Controls;
using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::ApplicationModel::DataTransfer;
using namespace winrt::Windows::Foundation::Collections;
using namespace std::chrono;
@@ -40,6 +41,69 @@ namespace winrt::Vav2Player::implementation
}
}
+ void LogMessagePage::CopyLogButton_Click(IInspectable const&, RoutedEventArgs const&)
+ {
+ try
+ {
+ std::wstring allLogText;
+
+ // Collect all log messages from the UI collection
+ {
+ std::lock_guard lock(m_uiUpdateMutex);
+
+ for (uint32_t i = 0; i < m_logCollection.Size(); ++i)
+ {
+ if (auto logString = m_logCollection.GetAt(i).try_as())
+ {
+ allLogText += logString->c_str();
+ allLogText += L"\r\n"; // Windows line ending for clipboard
+ }
+ }
+ }
+
+ if (!allLogText.empty())
+ {
+ // Remove the last line ending
+ if (allLogText.length() >= 2)
+ {
+ allLogText = allLogText.substr(0, allLogText.length() - 2);
+ }
+
+ // Copy to clipboard using Windows API
+ if (OpenClipboard(NULL))
+ {
+ EmptyClipboard();
+
+ size_t len = (allLogText.length() + 1) * sizeof(wchar_t);
+ HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, len);
+
+ if (hMem != NULL)
+ {
+ wchar_t* pMem = static_cast(GlobalLock(hMem));
+ if (pMem != NULL)
+ {
+ wcscpy_s(pMem, allLogText.length() + 1, allLogText.c_str());
+ GlobalUnlock(hMem);
+ SetClipboardData(CF_UNICODETEXT, hMem);
+ }
+ }
+
+ CloseClipboard();
+ }
+
+ // Logs copied to clipboard - no need to log this action
+ }
+ else
+ {
+ // No log messages to copy - no need to log this
+ }
+ }
+ catch (...)
+ {
+ // Failed to copy logs - no need to log this error
+ }
+ }
+
void LogMessagePage::ClearLogButton_Click(IInspectable const&, RoutedEventArgs const&)
{
// Clear logs in LogManager (single source of truth)
@@ -52,8 +116,7 @@ namespace winrt::Vav2Player::implementation
LogCountText().Text(L"0 messages");
} // Release mutex before logging to avoid deadlock
- // Log the clear action (called after releasing mutex to prevent deadlock)
- ::Vav2Player::LogManager::GetInstance().LogInfo(L"Log cleared by user", L"LogMessagePage");
+ // Log cleared - no need to log this action
}
void LogMessagePage::AutoScrollCheckBox_CheckedChanged(IInspectable const& sender, RoutedEventArgs const&)
@@ -251,4 +314,52 @@ namespace winrt::Vav2Player::implementation
default: return L"UNKNOWN";
}
}
+
+ void LogMessagePage::SetLogItemBackground(uint32_t index, LogLevel level)
+ {
+ // This approach doesn't work well with ItemsControl template system.
+ // Instead, we'll modify the approach to use a custom DataTemplate with binding.
+ // For now, we'll skip the background coloring and implement a simpler solution.
+
+ // TODO: Implement background coloring using a different approach
+ }
+
+ void LogMessagePage::LogBorder_Loaded(IInspectable const& sender, RoutedEventArgs const&)
+ {
+ try
+ {
+ if (auto border = sender.try_as())
+ {
+ // Find the TextBlock child to get the log text
+ if (auto textBlock = border.Child().try_as())
+ {
+ auto logText = std::wstring(textBlock.Text().c_str());
+
+ // Check log level in the text and set background color accordingly
+ if (logText.find(L"ERROR:") != std::wstring::npos)
+ {
+ // Light red background for ERROR logs (#FFE4E1)
+ border.Background(Microsoft::UI::Xaml::Media::SolidColorBrush(
+ Microsoft::UI::ColorHelper::FromArgb(255, 255, 228, 225)));
+ }
+ else if (logText.find(L"WARN:") != std::wstring::npos)
+ {
+ // Light yellow background for WARNING logs (#FFFACD)
+ border.Background(Microsoft::UI::Xaml::Media::SolidColorBrush(
+ Microsoft::UI::ColorHelper::FromArgb(255, 255, 250, 205)));
+ }
+ else
+ {
+ // White background for other log levels
+ border.Background(Microsoft::UI::Xaml::Media::SolidColorBrush(
+ Microsoft::UI::Colors::White()));
+ }
+ }
+ }
+ }
+ catch (...)
+ {
+ // Ignore errors in background color setting
+ }
+ }
}
\ No newline at end of file
diff --git a/vav2/Vav2Player/Vav2Player/LogMessagePage.xaml.h b/vav2/Vav2Player/Vav2Player/LogMessagePage.xaml.h
index dcd0b8b..78898cb 100644
--- a/vav2/Vav2Player/Vav2Player/LogMessagePage.xaml.h
+++ b/vav2/Vav2Player/Vav2Player/LogMessagePage.xaml.h
@@ -15,15 +15,27 @@ namespace winrt::Vav2Player::implementation
using LogLevel = ::Vav2Player::LogLevel;
using LogMessage = ::Vav2Player::LogMessage;
+ // UI wrapper for log messages with visual styling information
+ struct LogMessageUI
+ {
+ std::wstring text;
+ LogLevel level;
+ bool isError() const { return level == LogLevel::Error; }
+ bool isWarning() const { return level == LogLevel::Warning; }
+ bool isInfo() const { return level == LogLevel::Info || level == LogLevel::Debug; }
+ };
+
struct LogMessagePage : LogMessagePageT
{
LogMessagePage();
~LogMessagePage();
// Event handlers
+ void CopyLogButton_Click(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& e);
void ClearLogButton_Click(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& e);
void AutoScrollCheckBox_CheckedChanged(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& e);
void LogLevelFilterComboBox_SelectionChanged(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::Controls::SelectionChangedEventArgs const& e);
+ void LogBorder_Loaded(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& e);
// Observer pattern - LogMessagePage subscribes to LogManager updates
void InitializeLogObserver();
@@ -39,6 +51,7 @@ namespace winrt::Vav2Player::implementation
bool ShouldShowMessage(LogLevel level) const;
std::wstring GetLogLevelString(LogLevel level) const;
std::wstring FormatLogMessageForUI(const ::Vav2Player::LogMessage& message) const;
+ void SetLogItemBackground(uint32_t index, LogLevel level);
// UI state
LogLevel m_currentFilter = LogLevel::Debug; // Show all by default
diff --git a/vav2/Vav2Player/Vav2Player/MainWindow.xaml b/vav2/Vav2Player/Vav2Player/MainWindow.xaml
index 234193d..7fd5e22 100644
--- a/vav2/Vav2Player/Vav2Player/MainWindow.xaml
+++ b/vav2/Vav2Player/Vav2Player/MainWindow.xaml
@@ -36,16 +36,21 @@
-
+
-
-
+
+ PointerMoved="Splitter_PointerMoved"
+ PointerReleased="Splitter_PointerReleased"
+ PointerEntered="Splitter_PointerEntered"
+ PointerExited="Splitter_PointerExited">
+ Drag to resize log panel
+
diff --git a/vav2/Vav2Player/Vav2Player/MainWindow.xaml.cpp b/vav2/Vav2Player/Vav2Player/MainWindow.xaml.cpp
index 78cbfcb..1de4eb6 100644
--- a/vav2/Vav2Player/Vav2Player/MainWindow.xaml.cpp
+++ b/vav2/Vav2Player/Vav2Player/MainWindow.xaml.cpp
@@ -4,6 +4,7 @@
#include "MultiVideoPage.xaml.h"
#include "LayeredVideoPage.xaml.h"
#include "src/Logger/LogManager.h"
+#include
#if __has_include("MainWindow.g.cpp")
#include "MainWindow.g.cpp"
#endif
@@ -96,33 +97,46 @@ namespace winrt::Vav2Player::implementation
if (isChecked)
{
- // Show log panel
- LogPanelColumn().Width(GridLength(300));
+ // Show log panel with default width
+ LogPanelColumn().Width(GridLength(400));
LogPanelBorder().Visibility(Visibility::Visible);
- SplitterBorder().Visibility(Visibility::Visible);
}
else
{
// Hide log panel
LogPanelColumn().Width(GridLength(0));
LogPanelBorder().Visibility(Visibility::Collapsed);
- SplitterBorder().Visibility(Visibility::Collapsed);
}
- ::Vav2Player::LogManager::GetInstance().LogInfo(isChecked ? L"Log panel shown" : L"Log panel hidden", L"MainWindow");
+ // Log panel visibility toggled - no need to log this
}
}
+ // Drag-based splitter implementation
void MainWindow::Splitter_PointerPressed(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::Input::PointerRoutedEventArgs const& e)
{
- m_isDraggingSplitter = true;
- // Simplified for now - disable detailed pointer tracking
- m_lastPointerX = 0.0;
-
+ // Capture pointer first to ensure we receive subsequent events
if (auto border = SplitterBorder())
{
border.CapturePointer(e.Pointer());
+ border.Background(Microsoft::UI::Xaml::Media::SolidColorBrush(Microsoft::UI::Colors::CornflowerBlue()));
}
+
+ // Set drag state after capturing pointer
+ m_isDraggingSplitter = true;
+
+ // Store initial panel width
+ m_initialPanelWidth = LogPanelColumn().Width().Value;
+
+ // Store initial screen mouse position using Windows API
+ POINT screenPoint;
+ GetCursorPos(&screenPoint);
+ m_lastMouseX = static_cast(screenPoint.x);
+
+ // Mark event as handled to prevent bubbling
+ e.Handled(true);
+
+ // Splitter drag started - no need to log drag events
}
void MainWindow::Splitter_PointerMoved(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::Input::PointerRoutedEventArgs const& e)
@@ -130,8 +144,28 @@ namespace winrt::Vav2Player::implementation
if (!m_isDraggingSplitter)
return;
- // Simplified for now - no detailed pointer tracking
- // Just maintain current log panel width
+ // Get current screen mouse position using Windows API
+ POINT currentScreenPoint;
+ GetCursorPos(¤tScreenPoint);
+ double currentMouseX = static_cast(currentScreenPoint.x);
+
+ // Calculate relative mouse movement delta
+ double deltaX = currentMouseX - m_lastMouseX;
+ m_lastMouseX = currentMouseX;
+
+ // Get current panel width and apply delta
+ auto currentWidth = LogPanelColumn().Width().Value;
+ double newWidth = currentWidth + deltaX;
+
+ // Set only minimum limit (no maximum limit)
+ const double MIN_WIDTH = 200.0;
+ newWidth = std::max(MIN_WIDTH, newWidth);
+
+ // Update panel width immediately for natural dragging
+ LogPanelColumn().Width(GridLength(newWidth));
+
+ // Mark event as handled
+ e.Handled(true);
}
void MainWindow::Splitter_PointerReleased(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::Input::PointerRoutedEventArgs const& e)
@@ -140,10 +174,35 @@ namespace winrt::Vav2Player::implementation
{
m_isDraggingSplitter = false;
+ // Release pointer capture
if (auto border = SplitterBorder())
{
border.ReleasePointerCapture(e.Pointer());
+ border.Background(Microsoft::UI::Xaml::Media::SolidColorBrush(Microsoft::UI::Colors::LightGray()));
}
+
+ // Splitter drag completed - no need to log resize events
+
+ // Mark event as handled
+ e.Handled(true);
+ }
+ }
+
+ void MainWindow::Splitter_PointerEntered(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::Input::PointerRoutedEventArgs const&)
+ {
+ // Highlight on hover
+ if (auto border = SplitterBorder())
+ {
+ border.Background(Microsoft::UI::Xaml::Media::SolidColorBrush(Microsoft::UI::Colors::LightGray()));
+ }
+ }
+
+ void MainWindow::Splitter_PointerExited(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::Input::PointerRoutedEventArgs const&)
+ {
+ // Reset to default color
+ if (auto border = SplitterBorder())
+ {
+ border.Background(Microsoft::UI::Xaml::Media::SolidColorBrush(Microsoft::UI::Colors::DarkGray()));
}
}
diff --git a/vav2/Vav2Player/Vav2Player/MainWindow.xaml.h b/vav2/Vav2Player/Vav2Player/MainWindow.xaml.h
index 9331401..af68704 100644
--- a/vav2/Vav2Player/Vav2Player/MainWindow.xaml.h
+++ b/vav2/Vav2Player/Vav2Player/MainWindow.xaml.h
@@ -23,10 +23,12 @@ namespace winrt::Vav2Player::implementation
// Log panel handlers
void ShowLogToggle_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
- // Splitter handlers
+ // Drag-based splitter handlers
void Splitter_PointerPressed(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Input::PointerRoutedEventArgs const& e);
void Splitter_PointerMoved(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Input::PointerRoutedEventArgs const& e);
void Splitter_PointerReleased(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Input::PointerRoutedEventArgs const& e);
+ void Splitter_PointerEntered(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Input::PointerRoutedEventArgs const& e);
+ void Splitter_PointerExited(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Input::PointerRoutedEventArgs const& e);
// 성능 최적화된 비디오 렌더링 함수들
static void ConvertYUVToBGRA(const VavCoreVideoFrame& yuv_frame, uint8_t* bgra_buffer, uint32_t width, uint32_t height);
@@ -37,7 +39,8 @@ namespace winrt::Vav2Player::implementation
private:
bool m_isDraggingSplitter = false;
- double m_lastPointerX = 0.0;
+ double m_initialPanelWidth = 0.0;
+ double m_lastMouseX = 0.0;
winrt::Vav2Player::LogMessagePage m_logPanel{nullptr};
};
}
diff --git a/vav2/todo7.txt b/vav2/todo7.txt
index 4aba142..f8f5fa6 100644
--- a/vav2/todo7.txt
+++ b/vav2/todo7.txt
@@ -4,14 +4,9 @@ amd decoder 를 탑재해야해.
-> nvidia
-player UI 개선
-* webm 파일을 읽어서 av1 코덱이 아니면, 지원하지 않는 코덱이라고 텍스트 로그를 출력.
-
-UI 화면/버튼, 폰트 크기를 재조정. 메뉴바 크기를 재조정.
-
-
android player 를 만들어서 av1 디코딩 테스트 필요.
+
IAdaptiveVideoDecoder.h 인터페이스가 정말로 필요한 것일까? 재검토를 해봐줘.
@@ -20,5 +15,7 @@ CLAUDE.md 파일을 확인하여 현재 작업 상황을 점검하고 완료된
완료된 사항만 간단하게 적어주고, 불필요한 정보들은 최대한 줄여줘.
-● Now I understand. The VavCoreVideoFrame doesn't have a color_space field, and we need to update the MainWindow files
- to use VavCoreVideoFrame instead of the old VideoFrame. Let me fix these issues:
+player UI 화면/버튼, 폰트 크기를 재조정. 메뉴바 크기를 재조정.
+
+
+VavCoreVideoFrame 에는 color_space 변수가 없다. 차후에 이것을 사용할 기능이 들어가게 될까?