package DCOP;

use strict;
use vars qw($VERSION @ISA);

use DynaLoader;
use DCOP::Object;

@ISA = qw(DynaLoader);

$VERSION = '0.01';

bootstrap DCOP $VERSION;

# Returns a DCOP::Object that is logically bound to a specific object of a specific app
sub createObject
{
    my ($self, $app, $obj) = @_;
    $obj = "default" unless defined $obj;
    $self = {
        CLIENT  => $self,
        APP     => $app,
        OBJ     => $obj,
    };
    bless $self, "DCOP::Object";
}

# That's it :)

1;
__END__

=head1 NAME

DCOP - Perl extension for communcation with KDE's DCOP server

=head1 SYNOPSIS

use DCOP;

my $client = new DCOP;
$client->attach();
$running_apps = $client->registeredApplications();
$client->send("kmail", "KMailIface", "checkMail()");

my $kmail = $client->createObject("kmail", "KMailIface");
$kmail->openComposer("fred@outer.space",
                     undef,
                     undef,
                     "This is a mail initiated by DCOP.pm",
                     0,
                     "file:/home/joe/file/with/mail/to/send");

=head1 DESCRIPTION

The Desktop COmmunication Protocol is used by almost every KDE application
and is a lightweight but powerful IPC mechanism. For more information look at

http://developer.kde.org/documentation/library/2.0-api/dcop/HOWTO.html

This Perl extension can be used to send commands to any currently registered
DCOP application, as well as query which apps are registered and what
interfaces with what functions they offer. Additionally you can use DCOP::Object
to trigger DCOP sends or calls as native methods of DCOP::Object
(see the secion on Autoload Magic below).

=head2 Creation, Attachment and Registration

Creating a DCOP client is as simple as it gets:

  use DCOP;

  $client = new DCOP;

That's it. Some arguments to new are planned for future releases.
After creation the client is not attached to the server. The easiest way to
establish a connection is

  $client->attach();

which registers your DCOP client anonymously.
To register with a well known name use:

  $client->registerAs("fred");
NOTE: registerAs is currently disabled

To close the connection, simply call

  $client->detach();

=head2 Hello World!

Now that you have your client registered with the server, either anonymously
or by name, you can use it to query information about other registered applications.
To get a list with names of all clients, use:

  $client->registeredApplications();

To retrieve the Qt object hierarchy of an application, call

  $client->remoteObjects($appname);

Similarly you can get a list of supported interfaces with

  $client->remoteIterfaces($appname, $objectname);

And to know what you can do with all these nice interfaces, learn about their functions:

  $client->remoteFunctions($appname, $objectname);

=head2 Let them do something

To simply dispatch a command neglecting its return value, use

  $client->send($appname, $objectname, $function, ...);

If you're interested in the return value, consider call:

  $client->call($appname, $objectname, $function, ...);

=head2 Autoload Magic

A much more intuitive way to use send and call is via DCOP::Object. This class
is not intended for explicit instantiation and is merely a very small autoload stub.
To get a DCOP::Object, simply call

  $obj = $client->createObject($appname [, $objectname]);

The returned $obj is a DCOP::Object "bound" to the specified application and object
(or the app's default object if $objectname is omitted or undef). This DCOP::Object
has only two known methods, _app() and _object() which return the application and object
name respectively and are merely for internal use. Any other method you call will be
looked up in the functions() list of the target object. So, if you created it e.g. with

  $obj = $client->createObject("kmail", "KMailIface");

You can simply invoke

  $obj->checkMail();

instead of

  $client->send("kmail", "KMailIface", "checkMail()");

=head2 Detailed Reference

sub new(); [ class method ]

takes no arguments by now and returns a blessed reference to a new DCOP client.

sub attach();

returns a true value if the attachment succeeded or undef on error.

sub detach();

returns a true value if the client was successfully detached or undef on error.

sub isAttached();

returns true or undef whether the client is attached or not.

sub registerAs($appId [, $addPID]);
CURRENTLY DISABLED

registers the client with the name $appId or $appId with a number appended if a
client by that name already exists. If $addPID is true, the PID of the client is
appended to the appId, seperated by a hyphen. If addPID is ommited, it defaults to
true. To not add a PID, specify undef or zero.
registerAs returns the actual appId after the PID or possibly a sequence number has
been added.
If you call this method on an already attached or registered client, the old appId will
be replaced with the new one.

sub isRegistered();
CURRENTLY DISABLED

like isAttached but returns true only if the client used registerAs.

sub appId();

returns the appId the client is known as or undef if it's not registered or only
attached anonymously.

sub send($app, $object, $function [, ...])

dispatches a function call without waiting for completion and thus without retrieving
a return value. Returns true if a matching object has been found or undef otherwise.
$app is the name of a registered application,
$object the name of an object implemented by $app or undef for the default object,
$function is the signature of the function to be called.
Any following arguments are passed as parameters to the called function.
Make sure that they match the function's signature in count and types (see Datatypes below)
or your program will die. (This will be configurable in later versions)

sub call($app, $object, $function [, ...])

like send, but blocks until the called function returns and supplies the return value of that
function (see Datatypes below). In scalar context, the value returned is the function's return
value, in list context call returns a two element list with the first item set to the function's
repturn value and the second set to true or undef according to success or failure of the DCOP call.


sub findObject

not really implemented, yet.

sub emitDCOPSignal

dito.

sub isApplicationRegistered($app)

returns true if an application with the given name is known to the DCOP server or otherwise undef.

sub registeredApplications()

returns a reference to an array with the names of all currently registered applications.
On error it returns undef.

sub remoteObjects($app)

returns a reference to an array with the names of the objects supported by the named application.
On error it returns undef.

sub remoteInterfaces($app, $object)

returns a reference to an array with the names of the interfaces supported by the given application
and object. On error it returns undef.

sub remoteFunctions($app, $object)

returns a reference to an array with the names of the functions the specified interface supports.
The functions are returned as their signatures with parameter names and return type like

  QCStringList functions()

sub normalizeSignature($signature)

removes extraneous whitespace from a function signature.

sub canonicalizeSignature($signature)

mostly for internal use. Calls normalizeSignature and then strips parameter names and
return type from it.

=head2 Datatypes

The following datatypes are currently supported in arguments to send and call and as
return values:

=over 4

=item * int
mapped to scalar

=item * TQCString
mapped to scalar

=item * TQString (no Unicode support yet, just latin 1)
mapped to scalar

=item * QCStringList
mapped to a reference to an array of scalars.

=item * TQStringList
mapped to a reference to an array of scalars.

=item * TQPoint (untested)
mapped to a reference to a two elemtent array [$x, $y]
named value support via hash planned.

=item * TQSize (untested)
mapped to a reference to a two elemtent array [$width, $height]
named value support via hash planned.

=item * TQRect (untested)
mapped to a reference to a four elemtent array [$left, $top, $width, $height]
named value support via hash planned (including alternative right and bottom / width height)

=item * KURL (only TQString url() now)
mapped to scalar

=item * DCOPRef (partially)
mapped to DCOP::Object, methods like isNull() missing.

=back

=head1 BUGS
Most probably many. A lot of memory leaks I fear, but that has to be proven.
There are many important features missing also. By now, it is not possible to
use DCOP.pm to receive DCOP messages. That is planned.

=head1 AUTHOR

Malte Starostik, malte@kde.org

=head1 SEE ALSO

perl(1).

=cut

