summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjaromil <jaromil@949728d9-16ea-0310-a75c-cbdf8430a4b8>2006-03-03 17:07:54 (GMT)
committer jaromil <jaromil@949728d9-16ea-0310-a75c-cbdf8430a4b8>2006-03-03 17:07:54 (GMT)
commit340c68a4e9b4f34dcba4db66984a853098cd2a57 (patch)
tree10d602b5f25b3b788a7d8a704f9ae7289071ca85
parent86c84b29c8e491d419555997a53480ad0f4db696 (diff)
XMLRPC API completed with Open and Pause,
Stop and EOF behaviour fixed to keep the daemon running, new XMLRPC client example in python, documentation update and cleanup for 0.4 release. git-svn-id: svn://dyne.org/montevideo/ivysync@58 949728d9-16ea-0310-a75c-cbdf8430a4b8
-rw-r--r--README26
-rw-r--r--cmdline.cpp3
-rw-r--r--decoder.cpp52
-rw-r--r--decoder.h3
-rwxr-xr-xivysync-remote.py115
-rw-r--r--ivysync.c365
-rw-r--r--xmlrpc.cpp68
-rw-r--r--xmlrpc.h23
8 files changed, 256 insertions, 399 deletions
diff --git a/README b/README
index 2836314..2e8c00b 100644
--- a/README
+++ b/README
@@ -1,7 +1,7 @@
,-_/ .---.
' | . , . . \___ . . ,-. ,-.
.^ | | / | | \ | | | | |
- `--' `' `-| `---' `-| ' ' `-' [ver 0.3]
+ `--' `' `-| `---' `-| ' ' `-' [ver 0.4]
/| /|
`-' `-' by Denis "jaromil" Rojo
Montevideo Artlab R&D
@@ -18,11 +18,11 @@ IvySync reaches to sync up to 4 video channels with frame precision and
comes together with a user friendly graphical interface (GTK2) to edit
the playlists.
-With version 0.3 is now possible to remotely control the playback and
-skip positions on videos sending commands across the network (XMLRPC).
-Support for time based scheduling of different playlists is also
-implemented (but still lacking a graphical interface) to let a running
-syncstarter cycle various screening programs at different hours, days
+It is possible to remotely control the playback and skip positions on
+videos sending commands across the network (XMLRPC).
+Support for time based scheduling of different playlists is also
+implemented (but still lacking a graphical interface) to let a running
+syncstarter cycle various screening programs at different hours, days
or months.
@@ -48,21 +48,19 @@ Montevideo / Time Based Arts http://montevideo.nl
* professional grade low cost solution
- * remotely controllable playback
+ * remotely controllable playback (XMLRPC)
- * Graphical interface for playlist scheduling
+ * graphical interface for playlist scheduling
* extensible, scriptable and reliable *NIX technology
- * frame accurate sync of DVD quality audio/video
+ * frame accurate sync of DVD quality audio/video (MPEG2)
- * streaming playback from a local network
+ * streaming playback from a local network (with Samba)
* capable of syncing up to 4 videos
- * remotely controllable thru XMLRPC commands
-
- * time based scheduling of different playlists
+ * time based scheduling of multiple playlists
== requirements
@@ -76,7 +74,7 @@ Montevideo / Time Based Arts http://montevideo.nl
== disclaimer
- IvySync is Copyright (C) 2004-2006 by Denis "Jaromil" Rojo
+ IvySync is Copyright (C) 2004-2006 by Denis "Jaromil" Roio
# This source code is free software; you can redistribute it and/or
# modify it under the terms of the GNU Public License as published
diff --git a/cmdline.cpp b/cmdline.cpp
index 047e885..362e1c8 100644
--- a/cmdline.cpp
+++ b/cmdline.cpp
@@ -43,7 +43,7 @@ bool syncstart = false;
bool graphical = false;
bool dummytest = false;
bool rpcdaemon = false;
-int rpcdaemonport;
+int rpcdaemonport = 2640;
int videobuf = 64;
// our global vector holding all instantiated decoders
@@ -300,6 +300,7 @@ int main(int argc, char **argv) {
// instantiate all classes
new Play (xmlrpc, &decoders);
new Stop (xmlrpc, &decoders);
+ new Pause (xmlrpc, &decoders);
new GetPos(xmlrpc, &decoders);
new SetPos(xmlrpc, &decoders);
new Open (xmlrpc, &decoders);
diff --git a/decoder.cpp b/decoder.cpp
index 482f00c..8aee540 100644
--- a/decoder.cpp
+++ b/decoder.cpp
@@ -104,7 +104,7 @@ bool Decoder::setup(bool *sync, int bufsize) {
}
void Decoder::close() {
- if(playing) stop();
+ playing = false;
quit = true;
if(running) {
D("thread was running, waiting to join...");
@@ -122,14 +122,17 @@ void Decoder::update() {
case PLAY: // next
- if( position+1 > playlist.size()-1 ) stop();
- else position++;
+ if( position+1 > (int)playlist.size()-1 )
+ stop();
+ else
+ position++;
+ D("update: position is now %u", position);
break;
case CONT: // next or first if at the end
- if( position+1 > playlist.size()-1 ) position = 1;
+ if( position+1 > (int)playlist.size()-1 ) position = 1;
else position++;
break;
@@ -275,12 +278,14 @@ void Decoder::run() {
fclose(playlist_fd);
playlist_fd = 0;
+ clear();
} // run() thread loop
if(playlist_fd)
fclose(playlist_fd); // be sure we close
playlist_fd = 0;
+ clear();
D("thread %u finished", pthread_self());
return;
@@ -300,7 +305,7 @@ void Decoder::flush() {
}
// if there is a seek to do, do it now
- if(newfilepos > 0L) {
+ if((newfilepos > 0L) && playlist_fd) {
D("seeking to new position %lu", newfilepos);
fseek(playlist_fd, newfilepos, SEEK_SET);
filepos = newfilepos;
@@ -310,12 +315,37 @@ void Decoder::flush() {
bool Decoder::play() {
playing = true;
- return playing;
+ return true;
}
+
bool Decoder::stop() {
+ newfilepos = 1;
+ clear();
playing = false;
- return playing;
+ return true;
+}
+
+bool Decoder::pause() {
+ playing = false;
+ return true;
+}
+
+bool Decoder::clear() {
+ if(!fd) return false;
+
+ flush();
+
+ ::close(fd);
+
+ fd = ::open(device.c_str(), O_WRONLY|O_NDELAY,S_IWUSR|S_IWGRP|S_IWOTH);
+ if(fd<0) {
+ D("error opening device %s: %s",device.c_str(),strerror(errno));
+ return false;
+ }
+
+ return true;
}
+
bool Decoder::restart() {
playing = false;
position = 0;
@@ -354,7 +384,7 @@ bool Decoder::append(char *file) {
}
bool Decoder::insert(char *file, int pos) {
- if(pos > playlist.size() ) {
+ if(pos > (int)playlist.size() ) {
// playlist is smaller than pos: append at the end
playlist.push_back(file);
@@ -392,6 +422,12 @@ bool Decoder::remove(int pos) {
return false;
}
+bool Decoder::empty() {
+ playlist.clear();
+ position = 0;
+ return true;
+}
+
static time_t now_epoch;
static struct tm now;
diff --git a/decoder.h b/decoder.h
index a6afde5..96530f2 100644
--- a/decoder.h
+++ b/decoder.h
@@ -60,6 +60,7 @@ class Decoder : public Thread {
bool insert(char *file, int pos); ///< insert *file in playlist at pos
// bool remove(char *file); ///< remove the first occurrence of *file
bool remove(int pos); ///< remove the playlist entry at pos
+ bool empty(); ///< empty all the playlist discarding all entries
// save on file
int load();
@@ -71,6 +72,8 @@ class Decoder : public Thread {
bool play();
bool stop();
+ bool pause();
+ bool clear();
bool restart();
int getpos();
diff --git a/ivysync-remote.py b/ivysync-remote.py
new file mode 100755
index 0000000..5391447
--- /dev/null
+++ b/ivysync-remote.py
@@ -0,0 +1,115 @@
+#!/usr/bin/python
+
+# python xmlrpc client for ivysync
+# (C)2006 by Denis "Jaromil" Rojo
+# released under the GNU General Public License
+
+# general system functions
+import sys
+from string import atoi
+
+# Medusa and xmlrpclib client functions
+from socket import gethostname
+from xmlrpclib import Transport, dumps
+
+
+
+
+
+######################################################################
+# XMLRPC Client connection class
+
+class xmlrpc_connection:
+ """The xmlrpc_connection class tests the xmlrpc_server. You must
+ download and install the medusa and xmlrpclib libraries to run
+ this code: http://www.nightmare.com http://www.pythonware.com"""
+
+ def __init__(self, host=None, port=2640):
+ if host is None:
+ host = gethostname()
+ self.host = "%s:%s" % (host, port)
+ self.transport = Transport()
+
+ def remote(self, method, params=()):
+ """remote invokes the server with the method name and an
+ optional set of parameters. The return value is always a
+ tuple."""
+
+ response = self.transport.request(self.host,
+ '/RPC2',
+ dumps(params, method))
+ return response
+
+###################################################################
+
+
+
+
+
+###################################################################
+## MAIN
+
+
+
+if __name__ == '__main__':
+
+ commands = ("Play", "Stop", "Open", "Pause", "Quit", "GetPos", "SetPos")
+
+ connection = xmlrpc_connection()
+
+ cmd = sys.argv[1]
+
+ if not cmd in commands:
+
+ print "no valid command recognized, list of valid commands:"
+ print commands
+ sys.exit(2)
+
+
+ if cmd == "Quit":
+
+ (res,) = connection.remote(cmd, (0, 0))
+ if res == 1:
+ answer = "Server is now quitting"
+ else:
+ answer = "Server refuses to quit"
+
+
+ elif cmd == "SetPos":
+
+ chan = int( sys.argv[2] )
+ pos = int( sys.argv[3] )
+
+ (res,) = connection.remote(cmd, (chan, pos))
+ answer = "Channel " + str(chan) + " is now at " + str(pos) + "%"
+
+
+ elif cmd == "GetPos":
+
+ chan = int( sys.argv[2] )
+ (res,) = connection.remote(cmd, (chan, 0))
+ answer = "Channel " + str(chan) + " is now at " + str(res) + "%"
+
+
+
+ elif cmd == "Open":
+
+ chan = int(sys.argv[2] )
+ path = str(sys.argv[3] )
+ (res,) = connection.remote(cmd, (chan, path))
+ if res == 1:
+ answer = "File " + path + " opened on channel " + str(chan)
+ else:
+ answer = "Error opening file " + path
+
+ else: # all other commands needing only one argument (channel num)
+
+ chan = int( sys.argv[2] )
+
+ (res,) = connection.remote(cmd, (chan, 0))
+ if res == 1:
+ answer = "Command '" + cmd + "' succesfully executed on channel " + str(chan)
+ else:
+ answer = "Error executing command '" + cmd + "' on channel " + str(chan)
+
+ print answer # 42! ;D
diff --git a/ivysync.c b/ivysync.c
deleted file mode 100644
index 624e1ba..0000000
--- a/ivysync.c
+++ /dev/null
@@ -1,365 +0,0 @@
-
-/* IvySync - Video SyncStarter
- *
- * (c) Copyright 2004 Denis Roio aka jaromil <jaromil@dyne.org>
- * Nederlands Instituut voor Mediakunst
- *
- * This source code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Public License as published
- * by the Free Software Foundation; either version 2 of the License,
- * or (at your option) any later version.
- *
- * This source code 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.
- * Please refer to the GNU Public License for more details.
- *
- * You should have received a copy of the GNU Public License along with
- * this source code; if not, write to:
- * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * to compile this sourcecode: gcc -o ivysync ivysync.c -lpthreads
- * it should work on any POSIX system, including embedded hardware
- * wherever the IvyTV drivers can also run (see http://ivtv.sf.net)
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <getopt.h>
-#include <errno.h>
-#include <signal.h>
-#include <sys/select.h>
-#include <sys/poll.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <pthread.h>
-#include <time.h>
-
-#define MULTITHREADED 1
-
-#define DEBUG 1
-
-#define MAX_DEVICES 3
-#define MAX_FILES 32
-#define CHUNKSIZE 1024*64
-
-int syncstart = 0;
-
-int players = 0;
-
-int quitted = 0;
-
-int act_device = 0;
-
-struct decoder {
- // device stuff
- char dev_path[512];
- int dev_fd;
-
- // playlist stuff
- char *playlist[MAX_FILES];
- int pl_idx;
- FILE *pl_fd;
-
- // pthreads stuff
- pthread_t thread;
- pthread_attr_t thread_attr;
- pthread_mutex_t mutex;
-
- // The Buffer
- char buffo[CHUNKSIZE+1024];
-
- int initialized;
- int quit;
-};
-
-struct decoder dec[MAX_DEVICES];
-
-char *short_options = "-d:";
-const struct option long_options[] = {
- { "device", required_argument, NULL, 'd'},
- {0, 0, 0, 0}
-};
-
-void jsleep(int sec, long nsec) {
- struct timespec timelap;
- timelap.tv_sec = sec;
- timelap.tv_nsec = nsec;
- nanosleep(&timelap,NULL);
-}
-
-
-
-void quitproc (int Sig) { /* signal handling */
- int c;
- fprintf(stderr,"received signal %u on process %u\n",Sig,getpid());
- for(c=0;c<players;c++) dec[c].quit = 1;
- fprintf(stderr,"quitting threads...\n");
- jsleep(1,0);
-}
-
-
-void flush_video(int fd) {
- // poll interface to see when is ready for the next write()
-
- struct pollfd fdled;
- fdled.fd = fd;
- fdled.events=POLLOUT;
-
- while( poll(&fdled,1,1000) < 1 ) { // wait infinite until ready
- if(fdled.revents & POLLOUT) return;
- else fprintf(stderr,"device %i still not ready for writing\n",fd);
- }
-
-}
-
-void *runner(void *arg) {
- int c;
- int num;
- int written;
- int writing;
- char *buf;
- struct decoder *pdec;
-
- pdec = (struct decoder*)arg;
-
- // try to open the device
- pdec->dev_fd =
- open(pdec->dev_path,O_WRONLY|O_NDELAY,S_IWUSR|S_IWGRP|S_IWOTH);
- if(pdec->dev_fd<0) { // error opening device
- fprintf(stderr,"error opening %s: %s\n",
- pdec->dev_path,strerror(errno));
- // pthread_exit(NULL);
- return NULL;
- }
-
-
-#ifdef DEBUG
-
- // list the playlist
- fprintf(stderr,"decoder %s (fd:%i) playlist:\n",
- pdec->dev_path, pdec->dev_fd);
-
- for(c=0;pdec->playlist[c];c++) // parse thru playlist entries
- fprintf(stderr,"%i: %s\n",c,pdec->playlist[c]);
-
-#endif
-
-
- for(c=0;pdec->playlist[c];c++) { // play each entry
-
- // open playlist entry
- pdec->pl_fd = fopen( pdec->playlist[c], "rb" );
-
- // check for error here in case we loop playlists
- if(!pdec->pl_fd) {
- fprintf(stderr,"error opening %s: %s\n",
- pdec->playlist[c],strerror(errno));
- continue;
- }
-
- // fprintf(stderr,"playing %s\n", pdec->playlist[c]);
-
- do { // inner loop
-
- // read a chunk of buffer in
- num = fread(pdec->buffo,1,CHUNKSIZE,pdec->pl_fd);
-
- if( feof(pdec->pl_fd) || num<1 ) { // EOF
- fprintf(stderr,"end of file %s\n",pdec->playlist[c]);
- break;
- }
-
- //#ifdef DEBUG
- // else fprintf(stderr,"read %i bytes data\n",num);
- //#endif
-
- written = 0;
- writing = num;
- buf = pdec->buffo;
-
- // it was locked in the main() startup of the thread
- // unlock to signal that we are ready
- if(!syncstart) {
- // flush_video(pdec->dev_fd);
- pthread_mutex_unlock(&pdec->mutex);
- }
- // simple sync using a shared variable
- while(!syncstart) jsleep(0,1); // check every nanosecond
-
- // write it out all
- while(writing) { // writing loop
-
-
- buf += written;
- written = write(pdec->dev_fd, buf, writing);
- if(written<0) { // error on write
- // fprintf(stderr,"error writing on device %s: %s\n",
- // pdec->dev_path, strerror(errno));
- continue;
- }
-
- //#ifdef DEBUG
- // fprintf(stderr,"written %i bytes data\n",written);
- //#endif
-
- writing -= written;
-
- flush_video(pdec->dev_fd); // wait for non-blocking write
-
- }
-
- } while(num>0 && !pdec->quit); // read/write inner loop
-
- // close playlist entry
- fclose(pdec->pl_fd);
-
- } // for cycle thru playlist
-
- close(pdec->dev_fd);
-
- fprintf(stderr,"decoder on %s: playlist finished\n",pdec->dev_path);
- pdec->quit = 1;
- // pthread_exit(NULL);
- return NULL;
-}
-
-int cmdline(int argc, char **argv) {
- FILE *fd;
- int res;
-
- // zeroing all structs, like a constructor
- memset(dec,0,sizeof(struct decoder)*MAX_DEVICES);
-
- do {
- res = getopt_long(argc, argv, short_options, long_options, NULL);
-
- switch(res) {
-
- case 'd':
- act_device = atoi(optarg);
- break;
-
- case 1:
- //fprintf(stderr,"append %s to playlist %i\n",optarg,act_device);
- fd = fopen(optarg,"rb");
- if(fd) {
- dec[act_device].playlist[ dec[act_device].pl_idx ] = strdup(optarg);
- dec[act_device].pl_idx++;
- fclose(fd);
- dec[act_device].initialized = 1;
- } else fprintf(stderr,"error: file %s not readable\n",optarg);
-
- break;
-
- default: break;
-
- }
-
- } while(res > 0);
-
- return res;
-}
-
-
-int main(int argc, char **argv) {
- int c;
-
- /* register quit signal handlers */
- if (signal (SIGINT, quitproc) == SIG_ERR) {
- fprintf(stderr,"Couldn't install SIGINT handler\n");
- exit (0);
- }
- if (signal (SIGQUIT, quitproc) == SIG_ERR) {
- fprintf(stderr,"Couldn't install SIGQUIT handler\n");
- exit (0);
- }
- if (signal (SIGTERM, quitproc) == SIG_ERR) {
- fprintf(stderr,"Couldn't install SIGTERM handler\n");
- exit (0);
- }
-
-
- cmdline(argc, argv);
-
-#ifdef MULTITHREADED
- fprintf(stderr,"running on multiple threads\n");
-#else
- fprintf(stderr,"single thread player\n");
-#endif
-
-
-
-
- for(c=0; c<MAX_DEVICES; c++) {
-
-
- if(dec[c].initialized) { // open desired devices
-
- // formulate the device path
- sprintf(dec[c].dev_path,"/dev/video%i",16+c);
-
-#ifdef MULTITHREADED
-
- // initialize posix threads
- pthread_mutex_init(&dec[c].mutex,NULL);
- pthread_mutex_lock(&dec[c].mutex);
-
- pthread_attr_init(&dec[c].thread_attr);
-
- // fire up the thread
- fprintf(stderr,"firing up thread %i ...\n",c);
- pthread_create(&dec[c].thread, &dec[c].thread_attr, &runner, &dec[c]);
-
-
- pthread_mutex_lock(&dec[c].mutex); // blocks until thread is ready
-
-#else
-
- runner(&dec[c]);
- break;
-
-#endif
-
- players++;
-
- } // if we are here, device is correctly opened
-
- }
-
- fprintf(stderr,"%i players synchronized\n",players);
-
-
-#ifdef MULTITHREADED
-
- fprintf(stderr,"Waiting 1 second before startup...");
- jsleep(1,0);
- fprintf(stderr," GO!\n");
- syncstart = 1;
-
- while(players != quitted) {
-
- // check which threads quitted and join them
- // keep the count of quits to see when all players are finished
- for(c = 0 ; c < MAX_DEVICES ; c++) { // cycle thru players
- if(dec[c].initialized)
- if(dec[c].quit) {
- fprintf(stderr,"joining thread for decoder %s\n",dec[c].dev_path);
- pthread_join(dec[c].thread,NULL);
- dec[c].quit = 0;
- quitted++;
- }
- }
-
-
- }
-#endif
-
- fprintf(stderr,"quitting!\n");
-
- exit(1);
-}
diff --git a/xmlrpc.cpp b/xmlrpc.cpp
index 9872359..bab8c32 100644
--- a/xmlrpc.cpp
+++ b/xmlrpc.cpp
@@ -70,6 +70,11 @@ Stop::Stop(XmlRpcServer* srv, vector<Decoder*> *decoders)
IvySyncPublicMethod(decoders)
{ }
+Pause::Pause(XmlRpcServer* srv, vector<Decoder*> *decoders)
+ : XmlRpcServerMethod("Pause", srv),
+ IvySyncPublicMethod(decoders)
+{ }
+
GetPos::GetPos(XmlRpcServer* srv, vector<Decoder*> *decoders)
: XmlRpcServerMethod("GetPos", srv),
IvySyncPublicMethod(decoders)
@@ -104,6 +109,8 @@ void Quit::execute(XmlRpcValue &params, XmlRpcValue &result) {
}
+ result = 1.0;
+
::quit = true;
}
@@ -111,34 +118,50 @@ void Open::execute(XmlRpcValue &params, XmlRpcValue &result) {
int decnum;
char *path;
- if( params.size() != 2) {
+ if( params.size() < 2) {
E("XMLRPC: Open called with invalid number of arguments(%u)",
params.size() );
+ result = 0.0;
return;
}
// get out the decoder parameter
decnum = (int) params[0] -1;
Decoder *dec = get_decoder( decnum );
+ if(!dec) { result = 0.0; return; }
// get out the path to the file to be opened
path = (char*) (std::string(params[1])).c_str();
- D("Open decoder %u file %s", decnum, path);
- result = (double) dec->append(path);
+ D("XMLRPC: Open decoder %u file %s", decnum+1, path);
+
+ FILE *fd;
+ fd = fopen(path, "r");
+ if(!fd) {
+ result = 0.0;
+ return;
+ } else fclose(fd);
+
+ dec->empty();
+ dec->append(path);
+ result = 1.0;
+
}
void Play::execute(XmlRpcValue &params, XmlRpcValue &result) {
int decnum;
- if( params.size() != 1) {
+ if( params.size() < 1) {
E("XMLRPC: Play called with invalid number of arguments (%u)",
params.size() );
+ result = 0.0;
return;
}
decnum = (int) params[0] -1;
Decoder *dec = get_decoder( decnum );
- D("Play decoder %u", decnum );
+ if(!dec) { result = 0.0; return; }
+
+ D("XMLRPC: Play decoder %u", decnum+1 );
result = (double) dec->play();
}
@@ -147,26 +170,45 @@ void Play::execute(XmlRpcValue &params, XmlRpcValue &result) {
void Stop::execute(XmlRpcValue &params, XmlRpcValue &result) {
int decnum;
- if( params.size() != 1) {
+ if( params.size() < 1) {
E("XMLRPC: Stop called with invalid number of arguments (%u)",
params.size() );
+ result = 0.0;
return;
}
decnum = (int) params[0] -1;
Decoder *dec = get_decoder( decnum );
- D("Stop decoder %u", decnum);
+ if(!dec) { result = 0.0; return; }
+
+ D("XMLRPC: Stop decoder %u", decnum+1);
result = (double) dec->stop();
}
+void Pause::execute(XmlRpcValue &params, XmlRpcValue &result) {
+ int decnum;
+
+ if( params.size() < 1) {
+ E("XMLRPC: Pause called with invalid number of arguments (%u)",
+ params.size() );
+ result = 0.0;
+ return;
+ }
+
+ decnum = (int) params[0] -1;
+ Decoder *dec = get_decoder( decnum );
+ if(!dec) { result = 0.0; return; }
+ D("XMLRPC: Pause decoder %u", decnum+1);
+ result = (double) dec->pause();
+}
void GetPos::execute(XmlRpcValue &params, XmlRpcValue &result) {
int decnum;
double pos;
- if( params.size() != 1) {
+ if( params.size() < 1) {
E("XMLRPC: GetPos called with invalid number of arguments (%u)",
params.size() );
return;
@@ -174,16 +216,18 @@ void GetPos::execute(XmlRpcValue &params, XmlRpcValue &result) {
decnum = (int) params[0] -1;
Decoder *dec = get_decoder( decnum );
+ if(!dec) { result = 0.0; return; }
+
pos = (double) dec->getpos();
result = pos;
- D("GetPos decoder %u returns %d", decnum, pos);
+ D("XMLRPC: GetPos decoder %u returns %d", decnum+1, pos);
}
void SetPos::execute(XmlRpcValue &params, XmlRpcValue &result) {
int decnum;
- if( params.size() != 2) {
+ if( params.size() < 2) {
E("XMLRPC: SetPos called with invalid number of arguments (%u)",
params.size() );
return;
@@ -191,7 +235,9 @@ void SetPos::execute(XmlRpcValue &params, XmlRpcValue &result) {
decnum = (int) params[0] -1;
Decoder *dec = get_decoder( decnum );
- D("SetPos decoder %u", decnum);
+ if(!dec) { result = 0.0; return; }
+
+ D("XMLRPC: SetPos decoder %u", decnum+1);
dec->setpos( (int) params[1] );
}
diff --git a/xmlrpc.h b/xmlrpc.h
index 28585ad..202a3fc 100644
--- a/xmlrpc.h
+++ b/xmlrpc.h
@@ -31,6 +31,16 @@
using namespace XmlRpc;
+
+// METHODS:
+class Open;
+class Play;
+class Stop;
+class GetPos;
+class SetPos;
+class Quit;
+
+
class IvySyncDaemon {
public:
IvySyncDaemon(XmlRpcServer *srv);
@@ -100,6 +110,19 @@ public:
};
+class Pause : public XmlRpcServerMethod, IvySyncPublicMethod {
+public:
+
+ Pause(XmlRpcServer* srv, vector<Decoder*> *decoders);
+
+ ~Pause() { };
+
+ void execute(XmlRpcValue &params, XmlRpcValue &result);
+
+ std::string help() {
+ return std::string("Pause the channel"); }
+
+};
class GetPos : public XmlRpcServerMethod, IvySyncPublicMethod {
public: