2 Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include <sys/types.h>
26 #include <boost/thread.hpp>
27 #include <boost/algorithm/string.hpp>
29 #include "film_state.h"
32 #include "exceptions.h"
35 using namespace boost;
37 Player::Player (shared_ptr<const FilmState> fs, shared_ptr<const Screen> screen, Split split)
38 : _stdout_reader_should_run (true)
44 if (pipe (_mplayer_stdin) < 0) {
45 throw PlayError ("could not create pipe");
48 if (pipe (_mplayer_stdout) < 0) {
49 throw PlayError ("could not create pipe");
52 if (pipe (_mplayer_stderr) < 0) {
53 throw PlayError ("could not create pipe");
56 int const p = fork ();
58 throw PlayError ("could not fork for mplayer");
60 close (_mplayer_stdin[1]);
61 dup2 (_mplayer_stdin[0], STDIN_FILENO);
63 close (_mplayer_stdout[0]);
64 dup2 (_mplayer_stdout[1], STDOUT_FILENO);
66 close (_mplayer_stderr[0]);
67 dup2 (_mplayer_stderr[1], STDERR_FILENO);
69 char* p[] = { strdup ("TERM=xterm"), strdup ("DISPLAY=:0"), 0 };
73 s << "/usr/local/bin/mplayer";
75 s << " -vo x11 -noaspect -noautosub -nosub -vo x11 -noborder -slave -quiet -input nodefault-bindings:conf=/dev/null";
76 s << " -sws " << fs->scaler->mplayer_id ();
80 Position position = screen->position (fs->format);
81 Size screen_size = screen->size (fs->format);
82 Size const cropped_size = fs->cropped_size (fs->size);
85 vf << crop_string (Position (fs->left_crop, fs->top_crop), cropped_size);
86 s << " -geometry " << position.x << ":" << position.y;
90 Size split_size = cropped_size;
91 split_size.width /= 2;
92 vf << crop_string (Position (fs->left_crop, fs->top_crop), split_size);
93 screen_size.width /= 2;
94 s << " -geometry " << position.x << ":" << position.y;
99 Size split_size = cropped_size;
100 split_size.width /= 2;
101 vf << crop_string (Position (fs->left_crop + split_size.width, fs->top_crop), split_size);
102 screen_size.width /= 2;
103 s << " -geometry " << (position.x + screen_size.width) << ":" << position.y;
108 vf << ",scale=" << screen_size.width << ":" << screen_size.height;
110 pair<string, string> filters = Filter::ffmpeg_strings (fs->filters);
112 if (!filters.first.empty()) {
113 vf << "," << filters.first;
116 if (!filters.second.empty ()) {
117 vf << ",pp=" << filters.second;
120 s << " -vf " << vf.str();
121 s << " \"" << fs->content_path() << "\" ";
123 string cmd (s.str ());
125 vector<string> b = split_at_spaces_considering_quotes (cmd);
127 char** cl = new char*[b.size() + 1];
128 for (vector<string>::size_type i = 0; i < b.size(); ++i) {
129 cl[i] = strdup (b[i].c_str ());
136 e << "exec of mplayer failed " << strerror (errno);
137 throw PlayError (e.str ());
143 _stdout_reader = new boost::thread (boost::bind (&Player::stdout_reader, this));
149 _stdout_reader_should_run = false;
150 _stdout_reader->join ();
151 delete _stdout_reader;
153 close (_mplayer_stdin[0]);
154 close (_mplayer_stdout[1]);
155 kill (_mplayer_pid, SIGTERM);
159 Player::command (string c)
162 snprintf (buf, sizeof (buf), "%s\n", c.c_str ());
163 write (_mplayer_stdin[1], buf, strlen (buf));
167 Player::stdout_reader ()
169 while (_stdout_reader_should_run) {
171 int r = read (_mplayer_stdout[0], buf, sizeof (buf));
173 stringstream s (buf);
179 split (b, line, is_any_of ("="));
184 if (b[0] == "ANS_time_pos") {
185 set_position (atof (b[1].c_str ()));
186 } else if (b[0] == "ANS_pause") {
187 set_paused (b[1] == "yes");
194 snprintf (buf, sizeof (buf), "pausing_keep_force get_property time_pos\npausing_keep_force get_property pause\n");
195 write (_mplayer_stdin[1], buf, strlen (buf));
200 Player::set_position (float p)
202 /* XXX: could be an atomic */
203 boost::mutex::scoped_lock lm (_state_mutex);
208 Player::set_paused (bool p)
210 /* XXX: could be an atomic */
211 boost::mutex::scoped_lock lm (_state_mutex);
216 Player::position () const
218 boost::mutex::scoped_lock lm (_state_mutex);
223 Player::paused () const
225 boost::mutex::scoped_lock lm (_state_mutex);