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>
31 #include "exceptions.h"
34 using namespace boost;
36 Player::Player (shared_ptr<const FilmState> fs, shared_ptr<const Screen> screen, Split split)
37 : _stdout_reader_should_run (true)
43 if (pipe (_mplayer_stdin) < 0) {
44 throw PlayError ("could not create pipe");
47 if (pipe (_mplayer_stdout) < 0) {
48 throw PlayError ("could not create pipe");
51 if (pipe (_mplayer_stderr) < 0) {
52 throw PlayError ("could not create pipe");
55 int const p = fork ();
57 throw PlayError ("could not fork for mplayer");
59 close (_mplayer_stdin[1]);
60 dup2 (_mplayer_stdin[0], STDIN_FILENO);
62 close (_mplayer_stdout[0]);
63 dup2 (_mplayer_stdout[1], STDOUT_FILENO);
65 close (_mplayer_stderr[0]);
66 dup2 (_mplayer_stderr[1], STDERR_FILENO);
68 char* p[] = { strdup ("TERM=xterm"), strdup ("DISPLAY=:0"), 0 };
72 s << "/usr/local/bin/mplayer";
74 s << " -vo x11 -noaspect -noautosub -nosub -vo x11 -noborder -slave -quiet -input nodefault-bindings:conf=/dev/null";
75 s << " -sws " << fs->scaler->mplayer_id ();
79 Position position = screen->position (fs->format);
80 Size screen_size = screen->size (fs->format);
81 Size const cropped_size = fs->cropped_size (fs->size);
84 vf << crop_string (Position (fs->left_crop, fs->top_crop), cropped_size);
85 s << " -geometry " << position.x << ":" << position.y;
89 Size split_size = cropped_size;
90 split_size.width /= 2;
91 vf << crop_string (Position (fs->left_crop, fs->top_crop), split_size);
92 screen_size.width /= 2;
93 s << " -geometry " << position.x << ":" << position.y;
98 Size split_size = cropped_size;
99 split_size.width /= 2;
100 vf << crop_string (Position (fs->left_crop + split_size.width, fs->top_crop), split_size);
101 screen_size.width /= 2;
102 s << " -geometry " << (position.x + screen_size.width) << ":" << position.y;
107 vf << ",scale=" << screen_size.width << ":" << screen_size.height;
109 pair<string, string> filters = Filter::ffmpeg_strings (fs->filters);
111 if (!filters.first.empty()) {
112 vf << "," << filters.first;
115 if (!filters.second.empty ()) {
116 vf << ",pp=" << filters.second;
119 s << " -vf " << vf.str();
120 s << " \"" << fs->content_path() << "\" ";
122 string cmd (s.str ());
124 vector<string> b = split_at_spaces_considering_quotes (cmd);
126 char** cl = new char*[b.size() + 1];
127 for (vector<string>::size_type i = 0; i < b.size(); ++i) {
128 cl[i] = strdup (b[i].c_str ());
135 e << "exec of mplayer failed " << strerror (errno);
136 throw PlayError (e.str ());
142 _stdout_reader = new boost::thread (boost::bind (&Player::stdout_reader, this));
148 _stdout_reader_should_run = false;
149 _stdout_reader->join ();
150 delete _stdout_reader;
152 close (_mplayer_stdin[0]);
153 close (_mplayer_stdout[1]);
154 kill (_mplayer_pid, SIGTERM);
158 Player::command (string c)
161 snprintf (buf, sizeof (buf), "%s\n", c.c_str ());
162 write (_mplayer_stdin[1], buf, strlen (buf));
166 Player::stdout_reader ()
168 while (_stdout_reader_should_run) {
170 int r = read (_mplayer_stdout[0], buf, sizeof (buf));
172 stringstream s (buf);
178 split (b, line, is_any_of ("="));
183 if (b[0] == "ANS_time_pos") {
184 set_position (atof (b[1].c_str ()));
185 } else if (b[0] == "ANS_pause") {
186 set_paused (b[1] == "yes");
193 snprintf (buf, sizeof (buf), "pausing_keep_force get_property time_pos\npausing_keep_force get_property pause\n");
194 write (_mplayer_stdin[1], buf, strlen (buf));
199 Player::set_position (float p)
201 /* XXX: could be an atomic */
202 boost::mutex::scoped_lock lm (_state_mutex);
207 Player::set_paused (bool p)
209 /* XXX: could be an atomic */
210 boost::mutex::scoped_lock lm (_state_mutex);
215 Player::position () const
217 boost::mutex::scoped_lock lm (_state_mutex);
222 Player::paused () const
224 boost::mutex::scoped_lock lm (_state_mutex);