Supporters update.
[dcpomatic.git] / src / wx / player_stress_tester.cc
1 /*
2     Copyright (C) 2017-2020 Carl Hetherington <cth@carlh.net>
3
4     This file is part of DCP-o-matic.
5
6     DCP-o-matic is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     DCP-o-matic is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
18
19 */
20
21
22 #include "controls.h"
23 #include "player_stress_tester.h"
24 #include <dcp/raw_convert.h>
25 #include <dcp/util.h>
26 #include <dcp/warnings.h>
27 LIBDCP_DISABLE_WARNINGS
28 #include <wx/wx.h>
29 LIBDCP_ENABLE_WARNINGS
30 #include <boost/algorithm/string.hpp>
31 #include <boost/bind/bind.hpp>
32 #include <iostream>
33 #include <string>
34 #include <vector>
35
36
37 using std::cout;
38 using std::string;
39 using std::vector;
40 using dcp::raw_convert;
41 using boost::optional;
42
43
44 /* Interval to check for things to do with the stress script (in milliseconds) */
45 #define CHECK_INTERVAL 20
46
47
48 Command::Command (string line)
49         : type (NONE)
50         , int_param (0)
51 {
52         vector<string> bits;
53         boost::split (bits, line, boost::is_any_of(" "));
54         if (bits[0] == "O") {
55                 if (bits.size() != 2) {
56                         return;
57                 }
58                 type = OPEN;
59                 string_param = bits[1];
60         } else if (bits[0] == "P") {
61                 type = PLAY;
62         } else if (bits[0] == "W") {
63                 if (bits.size() != 2) {
64                         return;
65                 }
66                 type = WAIT;
67                 int_param = raw_convert<int>(bits[1]);
68         } else if (bits[0] == "S") {
69                 type = STOP;
70         } else if (bits[0] == "K") {
71                 if (bits.size() != 2) {
72                         return;
73                 }
74                 type = SEEK;
75                 int_param = raw_convert<int>(bits[1]);
76         } else if (bits[0] == "E") {
77                 type = EXIT;
78         }
79 }
80
81 PlayerStressTester::PlayerStressTester ()
82         : _parent (0)
83         , _controls (0)
84         , _suspended (false)
85 {
86
87 }
88
89
90 void
91 PlayerStressTester::setup (wxWindow* parent, Controls* controls)
92 {
93         _parent = parent;
94         _controls = controls;
95 }
96
97
98 void
99 PlayerStressTester::load_script (boost::filesystem::path file)
100 {
101         DCPOMATIC_ASSERT (_parent);
102
103         _timer.Bind (wxEVT_TIMER, boost::bind(&PlayerStressTester::check_commands, this));
104         _timer.Start (CHECK_INTERVAL);
105         vector<string> lines;
106         string const script = dcp::file_to_string(file);
107         boost::split (lines, script, boost::is_any_of("\n"));
108         for (auto i: lines) {
109                 _commands.push_back (Command(i));
110         }
111         _current_command = _commands.begin();
112 }
113
114 void
115 PlayerStressTester::check_commands ()
116 {
117         DCPOMATIC_ASSERT (_controls);
118
119         if (_suspended) {
120                 return;
121         }
122
123         if (_current_command == _commands.end()) {
124                 _timer.Stop ();
125                 cout << "ST: finished.\n";
126                 return;
127         }
128
129         switch (_current_command->type) {
130                 case Command::OPEN:
131                         LoadDCP(_current_command->string_param);
132                         ++_current_command;
133                         break;
134                 case Command::PLAY:
135                         cout << "ST: play\n";
136                         _controls->play ();
137                         ++_current_command;
138                         break;
139                 case Command::WAIT:
140                         /* int_param here is the number of milliseconds to wait */
141                         if (_wait_remaining) {
142                                 _wait_remaining = *_wait_remaining - CHECK_INTERVAL;
143                                 if (_wait_remaining < 0) {
144                                         cout << "ST: wait done.\n";
145                                         _wait_remaining = optional<int>();
146                                         ++_current_command;
147                                 }
148                         } else {
149                                 _wait_remaining = _current_command->int_param;
150                                 cout << "ST: waiting for " << *_wait_remaining << ".\n";
151                         }
152                         break;
153                 case Command::STOP:
154                         cout << "ST: stop\n";
155                         _controls->stop ();
156                         ++_current_command;
157                         break;
158                 case Command::NONE:
159                         ++_current_command;
160                         break;
161                 case Command::SEEK:
162                         /* int_param here is a number between 0 and 4095, corresponding to the possible slider positions */
163                         cout << "ST: seek to " << _current_command->int_param << "\n";
164                         _controls->seek (_current_command->int_param);
165                         ++_current_command;
166                         break;
167                 case Command::EXIT:
168                         wxTheApp->GetTopWindow()->Destroy();
169                         break;
170         }
171 }
172