/* skype_dbus_client.c: a simple command line client to Skype's DBus interface
read from STDIN and write to STDOUT */
#include <stdio.h>
#include <glib.h>
#include <stdlib.h>
#include <string.h>
#define DBUS_API_SUBJECT_TO_CHANGE
#include <dbus/dbus.h>
DBusConnection *connection;
/* iterate through DBus messages and print the string components */
static void print_iter( DBusMessageIter *iter )
{
do
{
int type = dbus_message_iter_get_arg_type( iter );
const char *str;
if ( type == DBUS_TYPE_INVALID ) break;
switch ( type )
{
case DBUS_TYPE_STRING: // it is a string message
dbus_message_iter_get_basic( iter, &str );
g_print( "%s\n", str );
break;
case DBUS_TYPE_VARIANT: // another set of items
{
DBusMessageIter subiter;
dbus_message_iter_recurse( iter, &subiter );
print_iter( &subiter );
break;
}
default:
break;
}
}
while ( dbus_message_iter_next( iter ) );
}
/* the handler gets called if the DBus connection receives any data */
static DBusHandlerResult notify_handler( DBusConnection *bus, DBusMessage *msg, void *user_data )
{
DBusMessageIter iter;
dbus_message_iter_init( msg, &iter );
print_iter( &iter );
return TRUE;
}
/* send a string to skype */
void sendToSkype( char *msg )
{
DBusMessageIter iter;
const int reply_timeout = -1; // do not timeout -- block
DBusMessage *reply;
DBusMessage *message;
DBusError error;
dbus_error_init( &error );
message = dbus_message_new_method_call(
"com.Skype.API",
"/com/Skype",
"com.Skype.API",
"Invoke"
);
if( !dbus_message_append_args( message, DBUS_TYPE_STRING, &msg, DBUS_TYPE_INVALID ) )
{
fprintf( stderr, "Error: reply is not except format\n" );
exit( 1 );
}
reply = dbus_connection_send_with_reply_and_block( connection, message, reply_timeout, &error );
if ( dbus_error_is_set( &error ) )
{
fprintf ( stderr, "Error: %s\n", error.message );
dbus_error_free( &error );
exit( 1 );
}
dbus_message_iter_init( reply, &iter );
print_iter( &iter );
if( dbus_error_is_set( &error ) )
{
fprintf( stderr, "Error: %s\n", error.message );
dbus_error_free( &error );
exit( 1 );
}
}
/* if the input is disconnected: exit the program */
gboolean hangup_handler( GIOChannel *source, GIOCondition condition, gpointer data )
{ exit( 0 ); }
/* input waiting: read and forward to skype */
gboolean input_handler( GIOChannel *source, GIOCondition condition, gpointer data )
{
char *b;
g_io_channel_read_line( source, &b, NULL, NULL, NULL );
if ( b == NULL ) { exit( 0 ); }
sendToSkype( b );
g_free( b );
return TRUE;
}
int main( int argc, char **argv )
{
DBusObjectPathVTable vtable;
GMainLoop *loop;
GIOChannel *in;
DBusError error;
dbus_error_init( &error );
connection = dbus_bus_get( DBUS_BUS_SESSION, &error );
if ( connection == NULL )
{
fprintf( stderr, "Failed to open connection to bus: %s\n", error.message );
dbus_error_free( &error );
exit( 1 );
}
loop = g_main_loop_new( NULL, FALSE );
in = g_io_channel_unix_new( 0 ); // open STDIN for reading
g_io_add_watch( in, G_IO_IN, input_handler, NULL ); // watch for input on STDIN
g_io_add_watch( in, G_IO_HUP, hangup_handler, NULL ); // watch for hangup of STDIN
dbus_connection_setup_with_g_main( connection, NULL ); // set up te DBus connection
vtable.message_function = notify_handler; // register handler for incoming data on DBus
dbus_connection_register_object_path( connection, "/com/Skype/Client", &vtable, 0 );
g_main_loop_run( loop ); // the main loop
return 0;
}