1 /*  smtube, a small youtube browser.
2     Copyright (C) 2012-2021 Ricardo Villalba <ricardo@smplayer.info>
3 
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.
8 
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.
13 
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 */
18 
19 #include "players.h"
20 #include <QApplication>
21 #include <QFile>
22 #include <QFileInfo>
23 #include <QDir>
24 #include <QSettings>
25 #include <QDebug>
26 #include "qtcompat.h"
27 
28 //#define D_PLAYERS
29 //#define DEBUG_FIND_EX
30 
31 #ifdef OS_UNIX_NOT_MAC
findExecutable(const QString & name)32 QString Player::findExecutable(const QString & name) {
33 	QByteArray env = qgetenv("PATH");
34 	QStringList search_paths = QString::fromLocal8Bit(env.constData()).split(':', QTC_SkipEmptyParts);
35 	for (int n = 0; n < search_paths.count(); n++) {
36 		QString candidate = search_paths[n] + "/" + name;
37 		#ifdef DEBUG_FIND_EX
38 		qDebug() << "Player::findExecutable: candidate:" << candidate;
39 		#endif
40 		QFileInfo info(candidate);
41 		if (info.isFile() && info.isExecutable()) {
42 			#ifdef DEBUG_FIND_EX
43 			qDebug() << "Player::findExecutable: executable found:" << candidate;
44 			#endif
45 			return candidate;
46 		}
47 	}
48 	return QString();
49 }
50 #endif
51 
executable(bool * found)52 QString Player::executable(bool * found) {
53 	if (found) *found = false;
54 
55 	QString bin = player_bin;
56 
57 	QFileInfo fi(bin);
58 	if (fi.exists() && fi.isExecutable() && !fi.isDir()) {
59 		if (found) *found = true;
60 		#ifdef DEBUG_FIND_EX
61 		qDebug() << "Player::executable: found " << bin;
62 		#endif
63 		return bin;
64 	} else {
65 		#ifdef DEBUG_FIND_EX
66 		qDebug() << "Player::executable: not found " << bin;
67 		#endif
68 	}
69 
70 	bin = qApp->applicationDirPath() + "/" + bin;
71 	fi.setFile(bin);
72 	if (fi.exists() && fi.isExecutable() && !fi.isDir()) {
73 		if (found) *found = true;
74 		#ifdef DEBUG_FIND_EX
75 		qDebug() << "Player::executable: found " << bin;
76 		#endif
77 		return bin;
78 	} else {
79 		#ifdef DEBUG_FIND_EX
80 		qDebug() << "Player::executable: not found " << bin;
81 		#endif
82 	}
83 
84 #ifdef OS_UNIX_NOT_MAC
85 	bin = findExecutable(player_bin);
86 	if (!bin.isEmpty()) {
87 		if (found) *found = true;
88 		#ifdef DEBUG_FIND_EX
89 		qDebug() << "Player::executable: found " << bin;
90 		#endif
91 		return bin;
92 	} else {
93 		#ifdef DEBUG_FIND_EX
94 		qDebug() << "Player::executable: executable for" << player_bin << "not found anywhere!";
95 		#endif
96 	}
97 #endif
98 
99 	return player_bin;
100 }
101 
102 
Players()103 Players::Players() {
104 #ifdef Q_OS_WIN
105 	list << Player("SMPlayer", "smplayer.exe", "%u", true, true, Player::Video)
106 		 << Player("SMPlayer (audio)", "smplayer.exe", "%u -media-title %t", true, false, Player::Audio)
107 		 << Player("SMPlayer (add to playlist)", "smplayer.exe", "-add-to-playlist %u", true, true, Player::VideoAudio);
108 #else
109 	list << Player("SMPlayer", "smplayer", "%u", true, true, Player::Video)
110 		 << Player("SMPlayer (audio)", "smplayer", "%u -media-title %t", true, false, Player::Audio)
111 		 << Player("SMPlayer (add to playlist)", "smplayer", "-add-to-playlist %u", true, true, Player::VideoAudio)
112 		 << Player("MPlayer", "mplayer", "%u -title %t", false, false, Player::Video)
113 		 << Player("VLC", "vlc", "%u --meta-title=%t", false, true, Player::VideoAudio)
114 		 << Player("Dragon Player", "dragon", "%u", false, false, Player::VideoAudio)
115 		 << Player("Totem", "totem", "%u", false, false, Player::VideoAudio)
116 		 << Player("GNOME-MPlayer", "gnome-mplayer", "%u", false, false, Player::VideoAudio)
117 		 << Player("mpv", "mpv", "%u --title=%t", false, true, Player::Video)
118 		 << Player("mpv + youtube-dl", "mpv", "--ytdl --ytdl-format=best %u", true, true, Player::Video);
119 	#ifdef D_PLAYERS
120 	list << Player("uget", "uget-gtk", "--quiet --folder=/tmp --filename=%f %u", false, false, Player::VideoAudio);
121 	#endif
122 #endif
123 	default_list = list;
124 	curr = 0;
125 }
126 
setAllPlayers(QList<Player> players)127 void Players::setAllPlayers(QList<Player> players) {
128 	list = players;
129 	available_players_cache.clear();
130 }
131 
availablePlayers()132 QList<Player> Players::availablePlayers() {
133 	if (!available_players_cache.isEmpty()) {
134 		return available_players_cache;
135 	}
136 
137 	QList<Player>  l;
138 	bool found;
139 	for (int n = 0; n < list.count(); n++) {
140 		QString exec = list[n].executable(&found);
141 		if (found) {
142 			qDebug() << "Players::availablePlayers:" << n << ":" << exec;
143 			l << list[n];
144 		}
145 	}
146 
147 	available_players_cache = l;
148 	return l;
149 }
150 
findName(QString name)151 int Players::findName(QString name) {
152 	for (int n = 0; n < list.count(); n++) {
153 		if (list[n].name() == name) return n;
154 	}
155 	return -1;
156 }
157 
save(QSettings * set)158 void Players::save(QSettings * set) {
159 	qDebug() << "Players::save";
160 
161 	set->beginGroup("players");
162 	set->setValue("count", list.count());
163 
164 	for (int n = 0; n < list.count(); n++) {
165 		QString section = QString("player_%1").arg(n);
166 		set->beginGroup(section);
167 		set->setValue("name", list[n].name());
168 		set->setValue("binary", list[n].binary());
169 		set->setValue("arguments", list[n].arguments());
170 		set->setValue("directplay", list[n].supportStreamingSites());
171 		set->setValue("online_tv", list[n].supportOnlineTV());
172 		set->setValue("supported_media", list[n].supportedMedia());
173 		set->setValue("resolution", list[n].preferredResolution());
174 		set->endGroup();
175 	}
176 
177 	set->endGroup();
178 }
179 
load(QSettings * set)180 void Players::load(QSettings * set) {
181 	qDebug() << "Players::load";
182 
183 	set->beginGroup("players");
184 	int count = set->value("count", 0).toInt();
185 
186 	if (count > 0) {
187 		list.clear();
188 
189 		for (int n = 0; n < count; n++) {
190 			QString section = QString("player_%1").arg(n);
191 			set->beginGroup(section);
192 			QString name = set->value("name", "").toString();
193 			QString binary = set->value("binary", "").toString();
194 			QString arguments = set->value("arguments", "").toString();
195 			bool support_streaming_sites = set->value("directplay", false).toBool();
196 			int supported_media = set->value("supported_media", Player::VideoAudio).toInt();
197 
198 			QVariant var = set->value("online_tv");
199 			bool support_online_tv = false;
200 			if (var.isValid()) {
201 				support_online_tv = var.toBool();
202 			}
203 			else
204 			if (supported_media != Player::Audio) {
205 				#ifdef Q_OS_WIN
206 				if (binary.contains("smplayer.exe")) support_online_tv = true;
207 				#else
208 				if (binary == "smplayer" || binary == "vlc" || binary == "mpv") support_online_tv = true;
209 				#endif
210 			}
211 
212 			int resolution = set->value("resolution", -1).toInt();
213 			list.push_back( Player(name, binary, arguments, support_streaming_sites, support_online_tv, (Player::Media) supported_media, resolution) );
214 			set->endGroup();
215 		}
216 	}
217 
218 	set->endGroup();
219 }
220