⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qmremotecontrol.cpp

📁 可以播放MP3,wma等文件格式的播放器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*  * qmremotecontrol.cpp * * $Id: qmremotecontrol.cpp,v 1.12.2.2 2002/10/10 21:40:52 kyllingstad Exp $ * * Apollo sound player: http://www.apolloplayer.org * Copyright(C) 2000-2002 Apollo Team.  See CREDITS file. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. * * The GNU General Public License is also available online at: * * http://www.gnu.org/copyleft/gpl.html */#include "qmremotecontrol.h"#include "qmmainwindow.h"#include "message.h"#include "qmconfig.h"#include "qmsongitem.h"#include <qapplication.h>#include <qsocketnotifier.h>#include <unistd.h>#include <errno.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/un.h>#include <pwd.h>#include <stdio.h>#include <fcntl.h>#include <iostream>#ifndef FALSE#define FALSE (0)#endif#ifndef TRUE#define TRUE (!FALSE)#endif/*!  \class QmRemoteControl qmremotecontrol.h  \brief Remote control - manages the socket for remote control, from xmms.  This code is from XMMS.  So programs used to control xmms should be able  to control apollo without any modification.   How it works:  A unix domain socket is bound to $TMP/$APPNAME_$USERNAME.$SESSIONNO.  ctrlsocket_func is called when data is available (a QSocketNotifier puts  it in the select(2) in Qt toplevel event loop).  A simple binary  protocol is used to get information and call functions in apollo.  Clients opens the socket, writes a command, reads answer and  disconnects.  The original variable names and datatypes from XMMS are  used.   ctrlsocket_func calls the required methods directly, so the only  change to the rest of apollo is an instantiation of QmRemoteControl in  the QmMainWindow constructor, and a call to setup_ctrlsocket.   Tested with the client programs:  xmmsctrl: command line tool suitable for scripting            http://www.gnu.org/gnulist/production/xmmsctrl.html  xmms-kde: kde2 panel (kicker) applet            http://xmms-kde.sourceforge.net/   Notes: $APPNAME above is take from config:stuff:app-name-for-socket and  defaults to xmms. */QmRemoteControl::QmRemoteControl()    : socketNotifier(0){	QString tmp = QmConfig::instance()->getString("stuff", "app-name-for-socket");	if (tmp.isEmpty())		app_name_for_socket = "xmms";	else		app_name_for_socket = strdup(tmp.latin1());}QmRemoteControl::~QmRemoteControl(){    if(socketNotifier)        delete socketNotifier;}/*! Opens the server socket, binds it to a file name, registers ctrlsocket_func as callback * \returns FALSE if something fails. */gbooleanQmRemoteControl::setup_ctrlsocket(){	struct sockaddr_un saddr;	gboolean retval = FALSE;	gint i;	if ((ctrl_fd = socket(AF_UNIX, SOCK_STREAM, 0)) != -1)	{		for (i = 0;; i++)		{			saddr.sun_family = AF_UNIX;			struct passwd *pwd = getpwuid(getuid());			const char *user_name = pwd ? pwd->pw_name : "wtf?"; // failure should be logged						snprintf(saddr.sun_path, 108, "%s/%s_%s.%d",					 g_get_tmp_dir(), app_name_for_socket, user_name, i);			if (!apollo_remote_is_running(i))			{				if ((unlink(saddr.sun_path) == -1) && errno != ENOENT)				{					QmMainWindow::mainwin->statusUpdate(new Message(Message::Error,                    "QmRemoteControl::setup_ctrlsocket: Failed to unlink %s (Error: %s)",					saddr.sun_path, strerror(errno)));				}			}			else			{				bool ami;				QmConfig::instance()->get("stuff", "allow-multiple-instances", ami);				if (ami)					continue;				QmMainWindow::mainwin->statusUpdate(new Message(Message::Status,                "Did not set up remote control socket since a sesson is already running, "				"and `allow-multiple-instances' is false or not set."));				break; 			}			if (bind(ctrl_fd, (struct sockaddr *) &saddr, sizeof (saddr)) != -1)			{				session_id = i;				listen(ctrl_fd, 100);				int tmp = fcntl(ctrl_fd, F_SETFL, O_NONBLOCK);				if (tmp == -1)				{					std::cerr << "QmRemoteControl::setup_ctrlsocket: fcntl gave " << errno << "\n";					return FALSE;				}				socketNotifier = new QSocketNotifier(static_cast<int>(ctrl_fd), QSocketNotifier::Read);				QObject::connect( socketNotifier, SIGNAL(activated(int)), this, SLOT(ctrlsocket_func()) );				socket_name = strdup(saddr.sun_path);				retval = TRUE;				break;			}			else			{				QmMainWindow::mainwin->statusUpdate(new Message(Message::Error, 				      "setup_ctrlsocket(): Failed to assign %s to a socket (Error: %s)",				      saddr.sun_path, strerror(errno)));				break;			}		}	}	else		QmMainWindow::mainwin->statusUpdate(new Message(Message::Error,		      "setup_ctrlsocket(): Failed to open socket: %s", strerror(errno)));	if (!retval)	{		if (ctrl_fd != -1)			close(ctrl_fd);		ctrl_fd = 0;	}	return retval;}gbooleanQmRemoteControl::apollo_remote_is_running(gboolean session){	return remote_cmd(session, CMD_PING);}gintQmRemoteControl::ctrlsocket_get_session_id(){	return session_id;}voidQmRemoteControl::cleanup_ctrlsocket(){	if (ctrl_fd)	{		close(ctrl_fd);		unlink(socket_name);		free(socket_name);		ctrl_fd = 0;	}}// nb: empty with comment as in xmmsvoidQmRemoteControl::start_ctrlsocket(){	// todo}voidQmRemoteControl::ctrl_write_packet(gint fd, gpointer data, gint length){	ServerPktHeader pkthdr;	pkthdr.version = XMMS_PROTOCOL_VERSION;	pkthdr.data_length = length;	write(fd, &pkthdr, sizeof (ServerPktHeader));	if (data && length > 0)		write(fd, data, length);}voidQmRemoteControl::ctrl_write_gint(gint fd, gint val){	ctrl_write_packet(fd, &val, sizeof (gint));}voidQmRemoteControl::ctrl_write_gfloat(gint fd, gfloat val){	ctrl_write_packet(fd, &val, sizeof (gfloat));}voidQmRemoteControl::ctrl_write_gboolean(gint fd, gboolean b){	ctrl_write_packet(fd, &b, sizeof (gboolean));}voidQmRemoteControl::ctrl_write_string(gint fd, gchar * string){	ctrl_write_packet(fd, string, string ? strlen(string) + 1 : 0);}voidQmRemoteControl::ctrl_ack_packet(PacketNode * pkt){	ctrl_write_packet(pkt->fd, NULL, 0);	close(pkt->fd);// 	if (pkt->data)// 		free(pkt->data);	free(pkt);}/*! Called when data can be read from the socket, processes a command */voidQmRemoteControl::ctrlsocket_func(){	fd_set set;	struct sockaddr_un saddr;	gint fd;	guint32 v[2], info[3], num;	PacketNode *pkt;	gpointer data;	guint len;	QmSongItem *tmp_song;		FD_ZERO(&set);	FD_SET(ctrl_fd, &set);	len = sizeof (saddr);	pkt = (PacketNode*) malloc(sizeof (PacketNode));	fd = accept(ctrl_fd, (struct sockaddr *) &saddr, &len);	if (fd == -1) 		return;		read(fd, &pkt->hdr, sizeof (ClientPktHeader));	if (pkt->hdr.data_length)	{		pkt->data = malloc(pkt->hdr.data_length);		read(fd, pkt->data, pkt->hdr.data_length);	}	else		pkt->data = 0;		pkt->fd = fd;	data = pkt->data;//	print_cmd(pkt->hdr.command);	switch (pkt->hdr.command)	{		case CMD_GET_VERSION:			ctrl_write_gint(pkt->fd, 0x09a3); // rk: what? 			ctrl_ack_packet(pkt);			break;		case CMD_IS_PLAYING:			ctrl_write_gboolean(pkt->fd, (QmMainWindow::mainwin->playingState()==QmMainWindow::Playing ? 1 : 0));			ctrl_ack_packet(pkt);			break;		case CMD_IS_PAUSED:			ctrl_write_gboolean(pkt->fd, (QmMainWindow::mainwin->playingState()==QmMainWindow::Paused ? 1 : 0));			ctrl_ack_packet(pkt);			break;		case CMD_GET_PLAYLIST_POS:			ctrl_write_gint(pkt->fd, QmMainWindow::mainwin->playListPosition());			ctrl_ack_packet(pkt);			break;		case CMD_GET_PLAYLIST_LENGTH:			ctrl_write_gint(pkt->fd, static_cast<gint>(QmMainWindow::mainwin->playListEntries()));			ctrl_ack_packet(pkt);			break;		case CMD_GET_OUTPUT_TIME:			if (QmMainWindow::mainwin->isPlaying())  				ctrl_write_gint(pkt->fd, QmMainWindow::mainwin->currentSongPlayedTime()*1000); 			else 				ctrl_write_gint(pkt->fd, 0);			ctrl_ack_packet(pkt);			break;		case CMD_GET_VOLUME:			v[0] = v[1] = QmMainWindow::mainwin->volume();			ctrl_write_packet(pkt->fd, v, sizeof (v));			ctrl_ack_packet(pkt);			break;		case CMD_GET_BALANCE:			ctrl_write_gint(pkt->fd, QmMainWindow::mainwin->volumeBalanse());			ctrl_ack_packet(pkt);			break;		case CMD_GET_SKIN:			ctrl_write_string(pkt->fd, "apollo");			ctrl_ack_packet(pkt);			break;		case CMD_GET_PLAYLIST_FILE:			ctrl_write_string(pkt->fd, const_cast<gchar*>(QmMainWindow::mainwin->playListFile().latin1()));			ctrl_ack_packet(pkt);			break;		case CMD_GET_PLAYLIST_TITLE: 			if (pkt->data) 			{				if ((tmp_song = QmMainWindow::mainwin->song(*((guint32 *) pkt->data)))) 					ctrl_write_string(pkt->fd, const_cast<char*>(tmp_song->text(0).latin1()));				else 					ctrl_write_string(pkt->fd, NULL); 			} 			else				ctrl_write_string(pkt->fd, NULL);			ctrl_ack_packet(pkt);			break;		case CMD_GET_PLAYLIST_TIME: 			if (pkt->data && (tmp_song = QmMainWindow::mainwin->song(*((guint32 *) pkt->data)))) 				ctrl_write_gint(pkt->fd, tmp_song->length()*1000); 			else				ctrl_write_gint(pkt->fd, -1);			ctrl_ack_packet(pkt);			break;		case CMD_GET_INFO:			info[0] = bitrate;			info[1] = frequency;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -