MPTrackUtilWine.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. /*
  2. * MPTrackUtilWine.cpp
  3. * -------------------
  4. * Purpose: Wine utility functions.
  5. * Notes : (currently none)
  6. * Authors: OpenMPT Devs
  7. * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
  8. */
  9. #include "stdafx.h"
  10. #include "MPTrackUtilWine.h"
  11. #include "Mptrack.h"
  12. #include "../common/misc_util.h"
  13. #include "../misc/mptWine.h"
  14. OPENMPT_NAMESPACE_BEGIN
  15. namespace Util
  16. {
  17. namespace Wine
  18. {
  19. class CExecutePosixShellScriptProgressDialog
  20. : public CDialog
  21. {
  22. protected:
  23. mpt::Wine::Context & wine;
  24. std::string m_Title;
  25. std::string m_Status;
  26. bool m_bAbort;
  27. std::string m_script;
  28. FlagSet<mpt::Wine::ExecFlags> m_Flags;
  29. std::map<std::string, std::vector<char> > m_Filetree;
  30. mpt::Wine::ExecResult m_ExecResult;
  31. std::string m_ExceptionString;
  32. public:
  33. CExecutePosixShellScriptProgressDialog(mpt::Wine::Context & wine, std::string script, FlagSet<mpt::Wine::ExecFlags> flags, std::map<std::string, std::vector<char> > filetree, std::string title, std::string status, CWnd *parent = NULL);
  34. BOOL OnInitDialog();
  35. void OnCancel();
  36. afx_msg void OnButton1();
  37. static mpt::Wine::ExecuteProgressResult ProgressCancelCallback(void *userdata);
  38. static void ProgressCallback(void *userdata);
  39. mpt::Wine::ExecuteProgressResult Progress(bool allowCancel);
  40. void MessageLoop();
  41. mpt::Wine::ExecResult GetExecResult() const;
  42. std::string GetExceptionString() const;
  43. private:
  44. DECLARE_MESSAGE_MAP()
  45. };
  46. BEGIN_MESSAGE_MAP(CExecutePosixShellScriptProgressDialog, CDialog)
  47. ON_COMMAND(IDC_BUTTON1, &CExecutePosixShellScriptProgressDialog::OnButton1)
  48. END_MESSAGE_MAP()
  49. CExecutePosixShellScriptProgressDialog::CExecutePosixShellScriptProgressDialog(mpt::Wine::Context & wine, std::string script, FlagSet<mpt::Wine::ExecFlags> flags, std::map<std::string, std::vector<char> > filetree, std::string title, std::string status, CWnd *parent)
  50. : CDialog(IDD_PROGRESS, parent)
  51. , wine(wine)
  52. , m_Title(title)
  53. , m_Status(status)
  54. , m_bAbort(false)
  55. , m_script(script)
  56. , m_Flags(flags)
  57. , m_Filetree(filetree)
  58. , m_ExecResult(mpt::Wine::ExecResult::Error())
  59. {
  60. return;
  61. }
  62. void CExecutePosixShellScriptProgressDialog::OnCancel()
  63. {
  64. m_bAbort = true;
  65. }
  66. mpt::Wine::ExecuteProgressResult CExecutePosixShellScriptProgressDialog::ProgressCancelCallback(void *userdata)
  67. {
  68. return reinterpret_cast<CExecutePosixShellScriptProgressDialog*>(userdata)->Progress(true);
  69. }
  70. void CExecutePosixShellScriptProgressDialog::ProgressCallback(void *userdata)
  71. {
  72. reinterpret_cast<CExecutePosixShellScriptProgressDialog*>(userdata)->Progress(false);
  73. }
  74. void CExecutePosixShellScriptProgressDialog::MessageLoop()
  75. {
  76. MSG msg;
  77. while(::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  78. {
  79. ::TranslateMessage(&msg);
  80. ::DispatchMessage(&msg);
  81. }
  82. }
  83. mpt::Wine::ExecResult CExecutePosixShellScriptProgressDialog::GetExecResult() const
  84. {
  85. return m_ExecResult;
  86. }
  87. std::string CExecutePosixShellScriptProgressDialog::GetExceptionString() const
  88. {
  89. return m_ExceptionString;
  90. }
  91. BOOL CExecutePosixShellScriptProgressDialog::OnInitDialog()
  92. {
  93. CDialog::OnInitDialog();
  94. SetWindowText(mpt::ToCString(mpt::Charset::UTF8, m_Title));
  95. SetDlgItemText(IDCANCEL, _T("Cancel"));
  96. SetWindowLong(::GetDlgItem(m_hWnd, IDC_PROGRESS1), GWL_STYLE, GetWindowLong(::GetDlgItem(m_hWnd, IDC_PROGRESS1), GWL_STYLE) | PBS_MARQUEE);
  97. ::SendMessage(::GetDlgItem(m_hWnd, IDC_PROGRESS1), PBM_SETMARQUEE, 1, 30); // 30 is Windows default, but Wine < 1.7.15 defaults to 0
  98. PostMessage(WM_COMMAND, IDC_BUTTON1);
  99. return TRUE;
  100. }
  101. mpt::Wine::ExecuteProgressResult CExecutePosixShellScriptProgressDialog::Progress(bool allowCancel)
  102. {
  103. if(m_bAbort)
  104. {
  105. return mpt::Wine::ExecuteProgressAsyncCancel;
  106. }
  107. ::ShowWindow(::GetDlgItem(m_hWnd, IDCANCEL), allowCancel ? SW_SHOW : SW_HIDE);
  108. MessageLoop();
  109. if(m_bAbort)
  110. {
  111. return mpt::Wine::ExecuteProgressAsyncCancel;
  112. }
  113. ::Sleep(10);
  114. return mpt::Wine::ExecuteProgressContinueWaiting;
  115. }
  116. void CExecutePosixShellScriptProgressDialog::OnButton1()
  117. {
  118. if(m_script.empty())
  119. {
  120. EndDialog(IDCANCEL);
  121. return;
  122. }
  123. SetDlgItemText(IDC_TEXT1, mpt::ToCString(mpt::Charset::UTF8, m_Status));
  124. MessageLoop();
  125. if(m_bAbort)
  126. {
  127. EndDialog(IDCANCEL);
  128. return;
  129. }
  130. ::Sleep(10);
  131. try
  132. {
  133. m_ExecResult = wine.ExecutePosixShellScript(m_script, m_Flags, m_Filetree, m_Title, &ProgressCallback, &ProgressCancelCallback, this);
  134. } catch(const mpt::Wine::Exception &e)
  135. {
  136. m_ExceptionString = mpt::get_exception_text<std::string>(e);
  137. EndDialog(IDCANCEL);
  138. return;
  139. }
  140. MessageLoop();
  141. if(m_bAbort)
  142. {
  143. EndDialog(IDCANCEL);
  144. return;
  145. }
  146. SetDlgItemText(IDC_TEXT1, _T("Done."));
  147. ::ShowWindow(::GetDlgItem(m_hWnd, IDCANCEL), SW_HIDE);
  148. for(int i = 0; i < 10; ++i)
  149. {
  150. MessageLoop();
  151. ::Sleep(10);
  152. }
  153. MessageLoop();
  154. EndDialog(IDOK);
  155. }
  156. static void ProgressCallback(void * /*userdata*/ )
  157. {
  158. MSG msg;
  159. while(::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  160. {
  161. ::TranslateMessage(&msg);
  162. ::DispatchMessage(&msg);
  163. }
  164. ::Sleep(10);
  165. }
  166. static mpt::Wine::ExecuteProgressResult ProgressCancelCallback(void *userdata)
  167. {
  168. ProgressCallback(userdata);
  169. return mpt::Wine::ExecuteProgressContinueWaiting;
  170. }
  171. mpt::Wine::ExecResult ExecutePosixShellScript(mpt::Wine::Context & wine, std::string script, FlagSet<mpt::Wine::ExecFlags> flags, std::map<std::string, std::vector<char> > filetree, std::string title, std::string status)
  172. {
  173. if(flags[mpt::Wine::ExecFlagProgressWindow])
  174. {
  175. CExecutePosixShellScriptProgressDialog dlg(wine, script, flags, filetree, title, status, theApp.GetMainWnd());
  176. if(dlg.DoModal() != IDOK)
  177. {
  178. if(!dlg.GetExceptionString().empty())
  179. {
  180. throw mpt::Wine::Exception(dlg.GetExceptionString());
  181. }
  182. throw mpt::Wine::Exception("Canceled.");
  183. }
  184. return dlg.GetExecResult();
  185. } else
  186. {
  187. return wine.ExecutePosixShellScript(script, flags, filetree, title, &ProgressCallback, &ProgressCancelCallback, nullptr);
  188. }
  189. }
  190. Dialog::Dialog(std::string title, bool terminal)
  191. : m_Terminal(terminal)
  192. , m_Title(title)
  193. {
  194. return;
  195. }
  196. std::string Dialog::Detect() const
  197. {
  198. std::string script;
  199. script += std::string() + "chmod u+x ./build/wine/dialog.sh" + "\n";
  200. return script;
  201. }
  202. std::string Dialog::DialogVar() const
  203. {
  204. if(m_Terminal)
  205. {
  206. return "./build/wine/dialog.sh tui";
  207. } else
  208. {
  209. return "./build/wine/dialog.sh gui";
  210. }
  211. }
  212. std::string Dialog::Title() const
  213. {
  214. return m_Title;
  215. }
  216. std::string Dialog::Status(std::string text) const
  217. {
  218. return std::string() + DialogVar() + " --infobox \"" + Title() + "\" \"" + text + "\"";
  219. }
  220. std::string Dialog::MessageBox(std::string text) const
  221. {
  222. return std::string() + DialogVar() + " --msgbox \"" + Title() + "\" \"" + text + "\"";
  223. }
  224. std::string Dialog::YesNo(std::string text) const
  225. {
  226. return std::string() + DialogVar() + " --yesno \"" + Title() + "\" \"" + text + "\"";
  227. }
  228. std::string Dialog::TextBox(std::string text) const
  229. {
  230. return std::string() + DialogVar() + " --textbox \"" + Title() + "\" \"" + text + "\"";
  231. }
  232. std::string Dialog::Progress(std::string text) const
  233. {
  234. return std::string() + DialogVar() + " --gauge \"" + Title() + "\" \"" + text + "\"";
  235. }
  236. } // namespace Wine
  237. } // namespace Util
  238. OPENMPT_NAMESPACE_END