1 //=============================================================================
2 //
3 //   File : MpXmmsInterface.cpp
4 //   Creation date : Fri 25 Mar 2005 20:04:54 by Szymon Stefanek
5 //
6 //   This file is part of the KVIrc IRC client distribution
7 //   Copyright (C) 2005-2010 Szymon Stefanek <pragma at kvirc dot net>
8 //
9 //   This program is FREE software. You can redistribute it and/or
10 //   modify it under the terms of the GNU General Public License
11 //   as published by the Free Software Foundation; either version 2
12 //   of the License, or (at your option) any later version.
13 //
14 //   This program is distributed in the HOPE that it will be USEFUL,
15 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
16 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 //   See the GNU General Public License for more details.
18 //
19 //   You should have received a copy of the GNU General Public License
20 //   along with this program. If not, write to the Free Software Foundation,
21 //   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 //
23 //   Thnx to Alexander Stillich <torque at pltn dot org> for Audacious
24 //   media player interface hints :)
25 //
26 //=============================================================================
27 
28 #include "MpXmmsInterface.h"
29 
30 #if(!defined(COMPILE_ON_WINDOWS) && !defined(COMPILE_ON_MAC) && !defined(COMPILE_ON_MINGW))
31 
32 #include "KviLocale.h"
33 
34 MP_IMPLEMENT_DESCRIPTOR(
35     KviXmmsInterface,
36     "xmms",
37     __tr2qs_ctx(
38         "An interface for the UNIX XMMS media player.\n"
39         "Download it from http://legacy.xmms2.org\n",
40         "mediaplayer"))
41 
42 MP_IMPLEMENT_DESCRIPTOR(
43     KviAudaciousClassicInterface,
44     "audacious classic",
45     __tr2qs_ctx(
46         "An interface for the UNIX Audacious media player.\n"
47         "Download it from http://audacious-media-player.org\n",
48         "mediaplayer"))
49 
50 static const char * xmms_lib_names[] = {
51 	"libxmms.so",
52 	"libxmms.so.1",
53 	"/usr/lib/libxmms.so",
54 	"/usr/lib/libxmms.so.1",
55 	"/usr/local/lib/libxmms.so",
56 	"/usr/local/lib/libxmms.so.1",
57 	nullptr
58 };
59 
60 static const char * audacious_lib_names[] = {
61 	"libaudacious.so",
62 	"libaudacious.so.4",
63 	"/usr/lib/libaudacious.so",
64 	"/usr/lib/libaudacious.so.4",
65 	"/usr/local/lib/libaudacious.so",
66 	"/usr/local/lib/libaudacious.so.4",
67 	nullptr
68 };
69 
KviXmmsInterface()70 KviXmmsInterface::KviXmmsInterface()
71     : MpInterface()
72 {
73 	m_pPlayerLibrary = nullptr;
74 	m_szPlayerLibraryName = "libxmms.so";
75 	m_pLibraryPaths = xmms_lib_names;
76 }
77 
~KviXmmsInterface()78 KviXmmsInterface::~KviXmmsInterface()
79 {
80 	if(m_pPlayerLibrary)
81 	{
82 		m_pPlayerLibrary->unload();
83 		delete m_pPlayerLibrary;
84 		m_pPlayerLibrary = nullptr;
85 	}
86 }
87 
KviAudaciousClassicInterface()88 KviAudaciousClassicInterface::KviAudaciousClassicInterface()
89     : KviXmmsInterface()
90 {
91 	m_szPlayerLibraryName = "libaudacious.so";
92 	m_pLibraryPaths = audacious_lib_names;
93 }
94 
95 KviAudaciousClassicInterface::~KviAudaciousClassicInterface()
96     = default;
97 
loadPlayerLibrary()98 bool KviXmmsInterface::loadPlayerLibrary()
99 {
100 	if(m_pPlayerLibrary && m_pPlayerLibrary->isLoaded())
101 		return true;
102 
103 	const char ** lib_name = m_pLibraryPaths;
104 	while(*lib_name)
105 	{
106 		m_pPlayerLibrary = new QLibrary(*lib_name);
107 		if(m_pPlayerLibrary->load())
108 		{
109 			m_szPlayerLibraryName = *lib_name;
110 			return true;
111 		}
112 		delete m_pPlayerLibrary;
113 		m_pPlayerLibrary = nullptr;
114 		lib_name++;
115 	}
116 	return false;
117 }
118 
lookupSymbol(const char * szSymbolName)119 void * KviXmmsInterface::lookupSymbol(const char * szSymbolName)
120 {
121 	if(!m_pPlayerLibrary)
122 	{
123 		if(!loadPlayerLibrary())
124 		{
125 			QString szTmp = QString(__tr2qs_ctx("Can't load the player library (%1)", "mediaplayer")).arg(m_szPlayerLibraryName);
126 			setLastError(szTmp);
127 			return nullptr;
128 		}
129 	}
130 	void * symptr = (void *)m_pPlayerLibrary->resolve(szSymbolName);
131 	if(!symptr)
132 	{
133 		QString szTmp = QString(__tr2qs_ctx("Can't find symbol %1 in %2", "mediaplayer")).arg(szSymbolName, m_szPlayerLibraryName);
134 		setLastError(szTmp);
135 	}
136 	return symptr;
137 }
138 
detect(bool)139 int KviXmmsInterface::detect(bool)
140 {
141 	void * sym = lookupSymbol("xmms_remote_play");
142 	return sym ? 80 : 0;
143 }
144 
145 #define XMMS_SIMPLE_CALL(__symname)                            \
146 	void (*sym)(int) = (void (*)(int))lookupSymbol(__symname); \
147 	if(!sym)                                                   \
148 		return false;                                          \
149 	sym(0);                                                    \
150 	return true;
151 
prev()152 bool KviXmmsInterface::prev()
153 {
154 	XMMS_SIMPLE_CALL("xmms_remote_playlist_prev")
155 }
156 
next()157 bool KviXmmsInterface::next()
158 {
159 	XMMS_SIMPLE_CALL("xmms_remote_playlist_next")
160 }
161 
play()162 bool KviXmmsInterface::play()
163 {
164 	XMMS_SIMPLE_CALL("xmms_remote_play")
165 }
166 
stop()167 bool KviXmmsInterface::stop()
168 {
169 	XMMS_SIMPLE_CALL("xmms_remote_stop")
170 }
171 
pause()172 bool KviXmmsInterface::pause()
173 {
174 	XMMS_SIMPLE_CALL("xmms_remote_pause")
175 }
176 
quit()177 bool KviXmmsInterface::quit()
178 {
179 	XMMS_SIMPLE_CALL("xmms_remote_quit")
180 }
181 
jumpTo(kvs_int_t & iPos)182 bool KviXmmsInterface::jumpTo(kvs_int_t & iPos)
183 {
184 	void (*sym)(int, int) = (void (*)(int, int))lookupSymbol("xmms_remote_jump_to_time");
185 	if(!sym)
186 		return false;
187 	sym(0, iPos);
188 	return true;
189 }
190 
setVol(kvs_int_t & iVol)191 bool KviXmmsInterface::setVol(kvs_int_t & iVol)
192 {
193 	void (*sym)(int, int) = (void (*)(int, int))lookupSymbol("xmms_remote_set_main_volume");
194 	if(!sym)
195 		return false;
196 	sym(0, 100 * iVol / 255);
197 	return true;
198 }
199 
getVol()200 int KviXmmsInterface::getVol()
201 {
202 	int (*sym)(int) = (int (*)(int))lookupSymbol("xmms_remote_get_main_volume");
203 	if(!sym)
204 		return -1;
205 	int iVol = sym(0);
206 	return iVol * 255 / 100;
207 }
208 
getRepeat()209 bool KviXmmsInterface::getRepeat()
210 {
211 	bool (*sym)(int) = (bool (*)(int))lookupSymbol("xmms_remote_is_repeat");
212 	if(!sym)
213 		return false;
214 	bool ret = sym(0);
215 	return ret;
216 }
217 
setRepeat(bool & bVal)218 bool KviXmmsInterface::setRepeat(bool & bVal)
219 {
220 	bool (*sym1)(int) = (bool (*)(int))lookupSymbol("xmms_remote_is_repeat");
221 	if(!sym1)
222 		return false;
223 	bool bNow = sym1(0);
224 	if(bNow != bVal)
225 	{
226 		void (*sym2)(int) = (void (*)(int))lookupSymbol("xmms_remote_toggle_repeat");
227 		if(!sym2)
228 			return false;
229 		sym2(0);
230 	}
231 	return true;
232 }
233 
getShuffle()234 bool KviXmmsInterface::getShuffle()
235 {
236 	bool (*sym)(int) = (bool (*)(int))lookupSymbol("xmms_remote_is_shuffle");
237 	if(!sym)
238 		return false;
239 	bool ret = sym(0);
240 	return ret;
241 }
242 
setShuffle(bool & bVal)243 bool KviXmmsInterface::setShuffle(bool & bVal)
244 {
245 	bool (*sym1)(int) = (bool (*)(int))lookupSymbol("xmms_remote_is_shuffle");
246 	if(!sym1)
247 		return false;
248 	bool bNow = sym1(0);
249 	if(bNow != bVal)
250 	{
251 		void (*sym2)(int) = (void (*)(int))lookupSymbol("xmms_remote_toggle_shuffle");
252 		if(!sym2)
253 			return false;
254 		sym2(0);
255 	}
256 	return true;
257 }
258 
status()259 MpInterface::PlayerStatus KviXmmsInterface::status()
260 {
261 	bool (*sym1)(int) = (bool (*)(int))lookupSymbol("xmms_remote_is_paused");
262 	if(sym1)
263 	{
264 		if(sym1(0))
265 			return MpInterface::Paused;
266 		bool (*sym2)(int) = (bool (*)(int))lookupSymbol("xmms_remote_is_playing");
267 		if(sym2)
268 		{
269 			if(sym2(0))
270 				return MpInterface::Playing;
271 			else
272 				return MpInterface::Stopped;
273 		}
274 	}
275 
276 	return MpInterface::Unknown;
277 }
278 
playMrl(const QString & mrl)279 bool KviXmmsInterface::playMrl(const QString & mrl)
280 {
281 	void (*sym)(int, char *) = (void (*)(int, char *))lookupSymbol("xmms_remote_playlist_add_url_string");
282 	QByteArray tmp = mrl.toLocal8Bit();
283 	if(!tmp.isEmpty())
284 	{
285 		if(sym)
286 		{
287 			sym(0, tmp.data());
288 			int (*sym1)(int) = (int (*)(int))lookupSymbol("xmms_remote_get_playlist_length");
289 			if(sym1)
290 			{
291 				int len = sym1(0);
292 				if(len > 0)
293 				{
294 					void (*sym2)(int, int) = (void (*)(int, int))lookupSymbol("xmms_remote_set_playlist_pos");
295 					if(sym2)
296 					{
297 						sym2(0, len - 1);
298 					}
299 					else
300 						return false;
301 				}
302 				else
303 					return false;
304 			}
305 			else
306 				return false;
307 		}
308 		else
309 			return false;
310 	}
311 	return true;
312 }
313 
nowPlaying()314 QString KviXmmsInterface::nowPlaying()
315 {
316 	int (*sym)(int) = (int (*)(int))lookupSymbol("xmms_remote_get_playlist_pos");
317 	if(!sym)
318 		return QString();
319 	int pos = sym(0);
320 	char * (*sym2)(int, int) = (char * (*)(int, int))lookupSymbol("xmms_remote_get_playlist_title");
321 	if(!sym2)
322 		return QString();
323 	return QString::fromLocal8Bit(sym2(0, pos));
324 }
325 
mrl()326 QString KviXmmsInterface::mrl()
327 {
328 	int (*sym)(int) = (int (*)(int))lookupSymbol("xmms_remote_get_playlist_pos");
329 	if(!sym)
330 		return QString();
331 	int pos = sym(0);
332 	char * (*sym2)(int, int) = (char * (*)(int, int))lookupSymbol("xmms_remote_get_playlist_file");
333 	if(!sym2)
334 		return QString();
335 	QString ret = QString::fromLocal8Bit(sym2(0, pos));
336 	if(ret.length() > 1)
337 		if(ret[0] == '/')
338 			ret.prepend("file://");
339 	return ret;
340 }
341 
position()342 int KviXmmsInterface::position()
343 {
344 	int (*sym)(int) = (int (*)(int))lookupSymbol("xmms_remote_get_playlist_pos");
345 	if(!sym)
346 		return -1;
347 	int pos = sym(0);
348 	int (*sym2)(int, int) = (int (*)(int, int))lookupSymbol("xmms_remote_get_output_time");
349 	if(!sym2)
350 		return -1;
351 	return sym2(0, pos);
352 }
353 
length()354 int KviXmmsInterface::length()
355 {
356 	int (*sym)(int) = (int (*)(int))lookupSymbol("xmms_remote_get_playlist_pos");
357 	if(!sym)
358 		return -1;
359 	int pos = sym(0);
360 	int (*sym2)(int, int) = (int (*)(int, int))lookupSymbol("xmms_remote_get_playlist_time");
361 	if(!sym2)
362 		return -1;
363 	return sym2(0, pos);
364 }
365 
getPlayListPos()366 int KviXmmsInterface::getPlayListPos()
367 {
368 	int (*sym)(int) = (int (*)(int))lookupSymbol("xmms_remote_get_playlist_pos");
369 	if(!sym)
370 		return -1;
371 	return sym(0);
372 }
373 
374 #endif //!COMPILE_ON_WINDOWS
375