diff --git a/tools/PsfPlayer/PsfPlayer.vcproj b/tools/PsfPlayer/PsfPlayer.vcproj index f3188242..44f4a297 100644 --- a/tools/PsfPlayer/PsfPlayer.vcproj +++ b/tools/PsfPlayer/PsfPlayer.vcproj @@ -205,6 +205,14 @@ RelativePath=".\Source\HighResTimer.h" > + + + + @@ -320,6 +328,10 @@ RelativePath=".\Source\win32_ui\MiniDebugger.h" > + + @@ -328,6 +340,14 @@ RelativePath=".\Source\win32_ui\PlayerWnd.h" > + + + + @@ -368,6 +388,10 @@ RelativePath=".\Source\win32_ui\StdAfx.h" > + + + +class CPlaylist +{ +public: + struct PLAYLIST_ITEM + { + std::wstring title; + double length; + }; + + typedef std::map PlaylistItemMap; + typedef PlaylistItemMap::const_iterator PlaylistItemMapIterator; + + typedef boost::signal OnItemChangeEvent; + + CPlaylist(); + virtual ~CPlaylist(); + + void AddItem(const char*, const CPsfTags&); + bool DoesItemExist(const char*); + + OnItemChangeEvent OnItemChange; + +private: + PlaylistItemMap m_playlistItems; +}; + +#endif diff --git a/tools/PsfPlayer/Source/PsfTags.cpp b/tools/PsfPlayer/Source/PsfTags.cpp index c3147a31..0f6d67aa 100644 --- a/tools/PsfPlayer/Source/PsfTags.cpp +++ b/tools/PsfPlayer/Source/PsfTags.cpp @@ -32,29 +32,105 @@ void CPsfTags::SetDefaultCharEncoding(const CHAR_ENCODING& encoding) m_defaultEncoding = encoding; } -bool CPsfTags::HasTag(const char* tagName) +bool CPsfTags::HasTag(const char* tagName) const { ConstTagIterator tagIterator = m_tags.find(tagName); return tagIterator != m_tags.end(); } -string CPsfTags::GetRawTagValue(const char* tagName) +string CPsfTags::GetRawTagValue(const char* tagName) const { ConstTagIterator tagIterator = m_tags.find(tagName); if(tagIterator == m_tags.end()) return ""; return tagIterator->second; } -wstring CPsfTags::GetTagValue(const char* tagName) +wstring CPsfTags::GetTagValue(const char* tagName) const { return m_stringConverter(GetRawTagValue(tagName)); } -wstring CPsfTags::DecodeTagValue(const char* value) +wstring CPsfTags::DecodeTagValue(const char* value) const { return m_stringConverter(string(value)); } +double CPsfTags::ConvertTimeString(const wchar_t* value) +{ + double time = 0; + + enum + { + STATE_CHECK_HAS_SEPARATOR, + STATE_CHECK_HAS_OTHER_SEPARATOR, + STATE_SPLIT_SECONDS_DECIMAL, + STATE_DONE + }; + + struct FindSeparator + { + const wchar_t* operator()(const wchar_t* string) + { + const wchar_t* separator = wcschr(string, ':'); + if(separator == NULL) + { + separator = wcschr(string, ';'); + } + return separator; + } + }; + + unsigned int currentState = STATE_CHECK_HAS_SEPARATOR; + std::wstring firstUnit; + + while(currentState != STATE_DONE) + { + if(currentState == STATE_CHECK_HAS_SEPARATOR) + { + const wchar_t* separator = FindSeparator()(value); + if(separator == NULL) + { + //No colon found -> doesn't have hours or minutes + currentState = STATE_SPLIT_SECONDS_DECIMAL; + continue; + } + + firstUnit = std::wstring(value, separator); + currentState = STATE_CHECK_HAS_OTHER_SEPARATOR; + value = separator + 1; + } + else if(currentState == STATE_CHECK_HAS_OTHER_SEPARATOR) + { + const wchar_t* separator = FindSeparator()(value); + std::wstring minutesStr, hoursStr; + if(separator == NULL) + { + //No colon found -> first unit is minutes + minutesStr = firstUnit; + } + else + { + hoursStr = firstUnit; + minutesStr = std::wstring(value, separator); + value = separator + 1; + } + int hours = wcstol(hoursStr.c_str(), NULL, 10); + int minutes = wcstol(minutesStr.c_str(), NULL, 10); + currentState = STATE_SPLIT_SECONDS_DECIMAL; + time += minutes * 60; + time += hours * 60 * 60; + } + else if(currentState == STATE_SPLIT_SECONDS_DECIMAL) + { + double seconds = wcstod(value, NULL); + time += seconds; + currentState = STATE_DONE; + } + } + + return time; +} + CPsfTags::ConstTagIterator CPsfTags::GetTagsBegin() const { return m_tags.begin(); diff --git a/tools/PsfPlayer/Source/PsfTags.h b/tools/PsfPlayer/Source/PsfTags.h index 7a3ac146..fce7944b 100644 --- a/tools/PsfPlayer/Source/PsfTags.h +++ b/tools/PsfPlayer/Source/PsfTags.h @@ -22,10 +22,12 @@ public: CPsfTags(const TagMap&); virtual ~CPsfTags(); void SetDefaultCharEncoding(const CHAR_ENCODING&); - bool HasTag(const char*); - std::string GetRawTagValue(const char*); - std::wstring GetTagValue(const char*); - std::wstring DecodeTagValue(const char*); + bool HasTag(const char*) const; + std::string GetRawTagValue(const char*) const; + std::wstring GetTagValue(const char*) const; + std::wstring DecodeTagValue(const char*) const; + + static double ConvertTimeString(const wchar_t*); ConstTagIterator GetTagsBegin() const; ConstTagIterator GetTagsEnd() const; diff --git a/tools/PsfPlayer/Source/PsfVm.cpp b/tools/PsfPlayer/Source/PsfVm.cpp index dd90633f..bce25a3b 100644 --- a/tools/PsfPlayer/Source/PsfVm.cpp +++ b/tools/PsfPlayer/Source/PsfVm.cpp @@ -275,7 +275,7 @@ void CPsfVm::ThreadProc() m_OnRunningStateChange(); } #else - if(!m_spuHandler || !m_spuHandler->HasFreeBuffers()) + if(m_spuHandler && !m_spuHandler->HasFreeBuffers()) { boost::this_thread::sleep(boost::posix_time::milliseconds(16)); m_spuHandler->RecycleBuffers(); @@ -309,7 +309,10 @@ void CPsfVm::ThreadProc() currentBlock++; if(currentBlock == blockCount) { - m_spuHandler->Write(samples, blockSize * blockCount, 44100); + if(m_spuHandler) + { + m_spuHandler->Write(samples, blockSize * blockCount, 44100); + } currentBlock = 0; } } diff --git a/tools/PsfPlayer/Source/win32_ui/MainWindow.cpp b/tools/PsfPlayer/Source/win32_ui/MainWindow.cpp index 470e1c85..5c3d6857 100644 --- a/tools/PsfPlayer/Source/win32_ui/MainWindow.cpp +++ b/tools/PsfPlayer/Source/win32_ui/MainWindow.cpp @@ -22,9 +22,9 @@ CMainWindow::SPUHANDLER_INFO CMainWindow::m_handlerInfo[] = { - { 1, _T("Win32 WaveOut"), _T("SH_WaveOut.dll") }, - { 2, _T("OpenAL"), _T("SH_OpenAL.dll") }, - { NULL, NULL, NULL }, + { 1, _T("Win32 WaveOut"), _T("SH_WaveOut.dll") }, + { 2, _T("OpenAL"), _T("SH_OpenAL.dll") }, + { NULL, NULL, NULL }, }; using namespace Framework; @@ -35,19 +35,27 @@ m_virtualMachine(virtualMachine), m_ready(false), m_frames(0), m_writes(0), +m_selectedAudioHandler(0), m_ejectButton(NULL), m_pauseButton(NULL), -m_aboutButton(NULL) +m_aboutButton(NULL), +m_playlistPanel(NULL) { - m_selectedAudioHandler = m_handlerInfo[0].id; + for(unsigned int i = 0; i < MAX_PANELS; i++) + { + m_panels[i] = NULL; + } - if(!DoesWindowClassExist(CLSNAME)) + if(!DoesWindowClassExist(CLSNAME)) { RegisterClassEx(&Win32::CWindow::MakeWndClass(CLSNAME)); } // Create(WNDSTYLEEX, CLSNAME, APP_NAME, WNDSTYLE, Win32::CRect(0, 0, 320, 480), NULL, NULL); - Create(WNDSTYLEEX, CLSNAME, APP_NAME, WNDSTYLE, Win32::CRect(0, 0, 200, 175), NULL, NULL); + + Win32::CRect clientRect(0, 0, 320, 480); + AdjustWindowRectEx(clientRect, WNDSTYLE, FALSE, WNDSTYLEEX); + Create(WNDSTYLEEX, CLSNAME, APP_NAME, WNDSTYLE, clientRect, NULL, NULL); SetClassPtr(); SetTimer(m_hWnd, 0, 1000, NULL); @@ -61,11 +69,13 @@ m_aboutButton(NULL) m_virtualMachine.OnNewFrame.connect(std::tr1::bind(&CMainWindow::OnNewFrame, this)); m_virtualMachine.OnBufferWrite.connect(std::tr1::bind(&CMainWindow::OnBufferWrite, this, std::tr1::placeholders::_1)); - m_virtualMachine.SetSpuHandler(std::tr1::bind(&CMainWindow::CreateHandler, m_handlerInfo[0].dllName)); + ChangeAudioPlugin(0); m_timerLabel = new Win32::CStatic(m_hWnd, _T(""), SS_CENTER); m_titleLabel = new Win32::CStatic(m_hWnd, _T(""), SS_CENTER | SS_NOPREFIX); + m_placeHolder = new Win32::CStatic(m_hWnd, Win32::CRect(0, 0, 1, 1), SS_BLACKRECT); + m_nextButton = new Win32::CButton(_T(">>"), m_hWnd, Win32::CRect(0, 0, 1, 1)); m_prevButton = new Win32::CButton(_T("<<"), m_hWnd, Win32::CRect(0, 0, 1, 1)); m_pauseButton = new Win32::CButton(_T("Pause"), m_hWnd, Win32::CRect(0, 0, 1, 1)); @@ -77,7 +87,7 @@ m_aboutButton(NULL) VerticalLayoutContainer( LayoutExpression(Win32::CLayoutWindow::CreateTextBoxBehavior(100, 15, m_titleLabel)) + LayoutExpression(Win32::CLayoutWindow::CreateTextBoxBehavior(100, 15, m_timerLabel)) + - LayoutExpression(CLayoutStretch::Create()) + + LayoutExpression(Win32::CLayoutWindow::CreateCustomBehavior(300, 200, 1, 1, m_placeHolder)) + HorizontalLayoutContainer( LayoutExpression(Win32::CLayoutWindow::CreateTextBoxBehavior(100, 30, m_prevButton)) + LayoutExpression(CLayoutStretch::Create()) + @@ -92,6 +102,7 @@ m_aboutButton(NULL) ) ); + //Create tray icon Win32::CTrayIcon* trayIcon = m_trayIconServer.Insert(); trayIcon->SetIcon(LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MAIN))); trayIcon->SetTip(_T("PsfPlayer")); @@ -99,12 +110,21 @@ m_aboutButton(NULL) m_trayIconServer.RegisterHandler(std::tr1::bind(&CMainWindow::OnTrayIconEvent, this, std::tr1::placeholders::_1, std::tr1::placeholders::_2)); + //Create play list panel + m_playlistPanel = new CPlaylistPanel(m_placeHolder->m_hWnd, m_playlist); + m_playlistPanel->OnItemDblClick.connect(std::tr1::bind(&CMainWindow::OnPlaylistItemDblClick, this, std::tr1::placeholders::_1)); + + //Initialize panels + m_panels[0] = m_playlistPanel; + CreateAudioPluginMenu(); UpdateAudioPluginMenu(); UpdateTimer(); UpdateTitle(); UpdateButtons(); RefreshLayout(); + + m_panels[0]->Show(SW_SHOW); } CMainWindow::~CMainWindow() @@ -117,14 +137,42 @@ void CMainWindow::RefreshLayout() RECT rc = GetClientRect(); m_layout->SetRect(rc.left + 10, rc.top + 10, rc.right - 10, rc.bottom - 10); m_layout->RefreshGeometry(); + + for(unsigned int i = 0; i < MAX_PANELS; i++) + { + CPanel* panel(m_panels[i]); + if(panel != NULL) + { + panel->RefreshLayout(); + } + } } CSoundHandler* CMainWindow::CreateHandler(const TCHAR* libraryPath) { typedef CSoundHandler* (*HandlerFactoryFunction)(); - HMODULE module = LoadLibrary(libraryPath); - HandlerFactoryFunction handlerFactory = reinterpret_cast(GetProcAddress(module, "HandlerFactory")); - CSoundHandler* result = handlerFactory(); + CSoundHandler* result = NULL; + try + { + HMODULE module = LoadLibrary(libraryPath); + if(module == NULL) + { + throw std::exception(); + } + + HandlerFactoryFunction handlerFactory = reinterpret_cast(GetProcAddress(module, "HandlerFactory")); + if(handlerFactory == NULL) + { + throw std::exception(); + } + + result = handlerFactory(); + } + catch(...) + { + tstring errorMessage = _T("Couldn't create sound handler present in '") + tstring(libraryPath) + _T("'."); + MessageBox(m_hWnd, errorMessage.c_str(), APP_NAME, 16); + } return result; } @@ -196,6 +244,11 @@ long CMainWindow::OnSize(unsigned int type, unsigned int width, unsigned int hei return TRUE; } +void CMainWindow::OnPlaylistItemDblClick(const char* path) +{ + Load(path); +} + void CMainWindow::OnTrayIconEvent(Win32::CTrayIcon* icon, LPARAM param) { switch(param) @@ -297,7 +350,7 @@ void CMainWindow::ChangeAudioPlugin(unsigned int pluginIdx) { SPUHANDLER_INFO* handlerInfo = m_handlerInfo + pluginIdx; m_selectedAudioHandler = handlerInfo->id; - m_virtualMachine.SetSpuHandler(std::tr1::bind(&CMainWindow::CreateHandler, handlerInfo->dllName)); + m_virtualMachine.SetSpuHandler(std::tr1::bind(&CMainWindow::CreateHandler, this, handlerInfo->dllName)); UpdateAudioPluginMenu(); } @@ -365,6 +418,9 @@ void CMainWindow::Load(const char* path) } m_virtualMachine.Resume(); + + m_playlist.AddItem(path, m_tags); + m_ready = true; } catch(const exception& except) @@ -374,6 +430,7 @@ void CMainWindow::Load(const char* path) MessageBox(m_hWnd, errorString.c_str(), NULL, 16); m_ready = false; } + UpdateTitle(); UpdateButtons(); UpdateTimer(); diff --git a/tools/PsfPlayer/Source/win32_ui/MainWindow.h b/tools/PsfPlayer/Source/win32_ui/MainWindow.h index 899840f1..04e39a06 100644 --- a/tools/PsfPlayer/Source/win32_ui/MainWindow.h +++ b/tools/PsfPlayer/Source/win32_ui/MainWindow.h @@ -4,11 +4,14 @@ #include "../PsfVm.h" #include "../PsfBase.h" #include "../PsfTags.h" +#include "../Playlist.h" #include "win32/Window.h" #include "win32/Static.h" #include "win32/Button.h" #include "win32/Layouts.h" #include "win32/TrayIconServer.h" +#include "Panel.h" +#include "PlaylistPanel.h" class CMainWindow : public Framework::Win32::CWindow { @@ -24,6 +27,11 @@ protected: long OnTimer(); private: + enum + { + MAX_PANELS = 1, + }; + struct SPUHANDLER_INFO { int id; @@ -31,7 +39,7 @@ private: const TCHAR* dllName; }; - static CSoundHandler* CreateHandler(const TCHAR*); + CSoundHandler* CreateHandler(const TCHAR*); void OnNewFrame(); void OnBufferWrite(int); @@ -41,6 +49,7 @@ private: void OnAbout(); void Load(const char*); + void OnPlaylistItemDblClick(const char*); void OnTrayIconEvent(Framework::Win32::CTrayIcon*, LPARAM); void DisplayTrayMenu(); void UpdateTimer(); @@ -55,6 +64,8 @@ private: Framework::Win32::CStatic* m_titleLabel; Framework::LayoutObjectPtr m_layout; + Framework::Win32::CStatic* m_placeHolder; + Framework::Win32::CButton* m_nextButton; Framework::Win32::CButton* m_prevButton; Framework::Win32::CButton* m_pauseButton; @@ -63,10 +74,14 @@ private: Framework::Win32::CTrayIconServer m_trayIconServer; + CPanel* m_panels[MAX_PANELS]; + CPlaylistPanel* m_playlistPanel; + HMENU m_popupMenu; CPsfVm& m_virtualMachine; CPsfTags m_tags; + CPlaylist m_playlist; bool m_ready; uint64 m_frames; int m_writes; diff --git a/tools/PsfPlayer/Source/win32_ui/Panel.h b/tools/PsfPlayer/Source/win32_ui/Panel.h new file mode 100644 index 00000000..6c089bfd --- /dev/null +++ b/tools/PsfPlayer/Source/win32_ui/Panel.h @@ -0,0 +1,16 @@ +#ifndef _PANEL_H_ +#define _PANEL_H_ + +#include "win32/Window.h" + +class CPanel : public Framework::Win32::CWindow +{ +public: + virtual ~CPanel() {} + virtual void RefreshLayout() = 0; + +private: + +}; + +#endif diff --git a/tools/PsfPlayer/Source/win32_ui/PlaylistPanel.cpp b/tools/PsfPlayer/Source/win32_ui/PlaylistPanel.cpp new file mode 100644 index 00000000..c1011cc5 --- /dev/null +++ b/tools/PsfPlayer/Source/win32_ui/PlaylistPanel.cpp @@ -0,0 +1,150 @@ +#include "PlaylistPanel.h" +#include "win32/Rect.h" +#include "TimeToString.h" +#include "string_cast.h" + +#define CLSNAME _T("PlaylistPanel") +#define WNDSTYLE (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_CHILD) +#define WNDSTYLEEX (0) +#define WM_UPDATEVIS (WM_USER + 1) + +using namespace Framework; + +CPlaylistPanel::CPlaylistPanel(HWND parentWnd, CPlaylist& playlist) +: m_playlistView(NULL) +, m_playlist(playlist) +, m_nextListViewKey(0) +{ + if(!DoesWindowClassExist(CLSNAME)) + { + RegisterClassEx(&Win32::CWindow::MakeWndClass(CLSNAME)); + } + + Create(WNDSTYLEEX, CLSNAME, _T(""), WNDSTYLE, Win32::CRect(0, 0, 1, 1), parentWnd, NULL); + SetClassPtr(); + + m_playlistView = new Win32::CListView(m_hWnd, Win32::CRect(0, 0, 1, 1), LVS_REPORT | LVS_SORTASCENDING); + m_playlistView->SetExtendedListViewStyle(m_playlistView->GetExtendedListViewStyle() | LVS_EX_FULLROWSELECT); + + CreateColumns(); + + m_playlist.OnItemChange.connect(std::tr1::bind(&CPlaylistPanel::OnPlaylistItemChange, this, std::tr1::placeholders::_1)); + + m_nextListViewKey = 0; +} + +CPlaylistPanel::~CPlaylistPanel() +{ + +} + +long CPlaylistPanel::OnNotify(WPARAM wParam, NMHDR* hdr) +{ + if(CWindow::IsNotifySource(m_playlistView, hdr)) + { + switch(hdr->code) + { + case NM_DBLCLK: + OnPlaylistViewDblClick(reinterpret_cast(hdr)); + break; + } + } + return FALSE; +} + +void CPlaylistPanel::OnPlaylistViewDblClick(NMITEMACTIVATE* itemActivate) +{ + if(itemActivate->iItem == -1) return; + uint32 param = m_playlistView->GetItemData(itemActivate->iItem); + ListViewKeyMap::right_const_iterator keyIterator = m_listViewKeys.right.find(param); + assert(keyIterator != m_listViewKeys.right.end()); + if(keyIterator != m_listViewKeys.right.end()) + { + OnItemDblClick(keyIterator->second.c_str()); + } +} + +void CPlaylistPanel::AddItem(uint32 key, const TCHAR* title, const TCHAR* length) +{ + LVITEM item; + memset(&item, 0, sizeof(LVITEM)); + item.pszText = const_cast(title); + item.lParam = key; + item.mask = LVIF_TEXT | LVIF_PARAM; + int itemIdx = m_playlistView->InsertItem(&item); + +// m_playlist->SetItemText(itemIndex, 1, TimeToString(length).c_str()); + m_playlistView->SetItemText(itemIdx, 1, length); +} + +void CPlaylistPanel::ModifyItem(uint32 key, const TCHAR* title, const TCHAR* length) +{ + int itemIdx = m_playlistView->FindItemData(key); + assert(itemIdx != -1); + if(itemIdx == -1) return; + + m_playlistView->SetItemText(itemIdx, 0, title); + m_playlistView->SetItemText(itemIdx, 1, length); +} + +void CPlaylistPanel::CreateColumns() +{ + LVCOLUMN column; + memset(&column, 0, sizeof(LVCOLUMN)); + column.pszText = _T("Title"); + column.mask = LVCF_TEXT; + m_playlistView->InsertColumn(0, &column); + + memset(&column, 0, sizeof(LVCOLUMN)); + column.pszText = _T("Length"); + column.mask = LVCF_TEXT; + m_playlistView->InsertColumn(1, &column); +} + +void CPlaylistPanel::OnPlaylistItemChange(const CPlaylist::PlaylistItemMapIterator& itemIterator) +{ + const CPlaylist::PLAYLIST_ITEM& item(itemIterator->second); + + std::tstring title, length; + title = string_cast(item.title); + length = TimeToString(item.length); + + ListViewKeyMap::left_const_iterator keyIterator(m_listViewKeys.left.find(itemIterator->first)); + if(keyIterator == m_listViewKeys.left.end()) + { + //Element + uint32 newKey = ++m_nextListViewKey; + m_listViewKeys.insert(ListViewKeyMap::value_type(itemIterator->first, newKey)); + AddItem(newKey, title.c_str(), length.c_str()); + } + else + { + uint32 key = keyIterator->second; + ModifyItem(key, title.c_str(), length.c_str()); + } +} + +void CPlaylistPanel::RefreshLayout() +{ + //Resize panel + { + Win32::CRect clientRect(0, 0, 0, 0); + ::GetClientRect(GetParent(), clientRect); + SetSizePosition(clientRect); + } + + //Resize list view + { + Win32::CRect clientRect(0, 0, 0, 0); + GetClientRect(clientRect); + m_playlistView->SetSizePosition(clientRect); + } + + //Resize columns + { + RECT clientRect = m_playlistView->GetClientRect(); + + m_playlistView->SetColumnWidth(0, 3 * clientRect.right / 4); + m_playlistView->SetColumnWidth(1, 1 * clientRect.right / 4); + } +} diff --git a/tools/PsfPlayer/Source/win32_ui/PlaylistPanel.h b/tools/PsfPlayer/Source/win32_ui/PlaylistPanel.h new file mode 100644 index 00000000..3996e761 --- /dev/null +++ b/tools/PsfPlayer/Source/win32_ui/PlaylistPanel.h @@ -0,0 +1,40 @@ +#ifndef _PLAYLISTPANEL_H_ +#define _PLAYLISTPANEL_H_ + +#include "Panel.h" +#include "Playlist.h" +#include "win32/ListView.h" +#include + +class CPlaylistPanel : public CPanel, public boost::signals::trackable +{ +public: + typedef boost::signal OnItemDblClickEvent; + + CPlaylistPanel(HWND, CPlaylist&); + virtual ~CPlaylistPanel(); + + void RefreshLayout(); + + OnItemDblClickEvent OnItemDblClick; + +protected: + long OnNotify(WPARAM, NMHDR*); + +private: + typedef boost::bimap ListViewKeyMap; + + void CreateColumns(); + void OnPlaylistItemChange(const CPlaylist::PlaylistItemMapIterator&); + void AddItem(uint32, const TCHAR*, const TCHAR*); + void ModifyItem(uint32, const TCHAR*, const TCHAR*); + void OnPlaylistViewDblClick(NMITEMACTIVATE*); + + CPlaylist& m_playlist; + Framework::Win32::CListView* m_playlistView; + ListViewKeyMap m_listViewKeys; + + uint32 m_nextListViewKey; +}; + +#endif diff --git a/tools/PsfPlayer/Source/win32_ui/TimeToString.h b/tools/PsfPlayer/Source/win32_ui/TimeToString.h new file mode 100644 index 00000000..f9be3368 --- /dev/null +++ b/tools/PsfPlayer/Source/win32_ui/TimeToString.h @@ -0,0 +1,26 @@ +#ifndef _TIMETOSTRING_H_ +#define _TIMETOSTRING_H_ + +#include + +template +static StringType TimeToString(double time) +{ +// StringType result, separator; + StringType separator; + separator += ':'; + unsigned int secs = static_cast(time) % 60; + unsigned int mins = static_cast(time) / 60; + std::basic_stringstream result; + result << mins << separator; + result.width(2); + result.fill('0'); + result << secs; +// result = +// boost::lexical_cast(mins) + +// separator + +// boost::lexical_cast(secs); + return result.str(); +} + +#endif