TelepathyQt4: call/call-handler.cpp

| Home · All Classes · All Namespaces · Modules · Functions · Files

    /*
     * This file is part of TelepathyQt4
     *
     * Copyright © 2009 Collabora Ltd. <http://www.collabora.co.uk/>
     * Copyright © 2009 Nokia Corporation
     *
     * This library is free software; you can redistribute it and/or
     * modify it under the terms of the GNU Lesser General Public
     * License as published by the Free Software Foundation; either
     * version 2.1 of the License, or (at your option) any later version.
     *
     * This library 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
     * Lesser General Public License for more details.
     *
     * You should have received a copy of the GNU Lesser General Public
     * License along with this library; if not, write to the Free Software
     * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     */

    #include "call-handler.h"
    #include "_gen/call-handler.moc.hpp"

    #include "call-widget.h"

    #include <TelepathyQt4/Channel>
    #include <TelepathyQt4/Connection>
    #include <TelepathyQt4/Contact>
    #include <TelepathyQt4/ContactManager>
    #include <TelepathyQt4/PendingChannel>
    #include <TelepathyQt4/PendingReady>
    #include <TelepathyQt4/ReferencedHandles>
    #include <TelepathyQt4/StreamedMediaChannel>

    #include <QDebug>
    #include <QMessageBox>

    using namespace Tp;

    CallHandler::CallHandler(QObject *parent)
        : QObject(parent)
    {
    }

    CallHandler::~CallHandler()
    {
        foreach (CallWidget *call, mCalls) {
            call->close();
        }
    }

    void CallHandler::addOutgoingCall(const ContactPtr &contact)
    {
        QVariantMap request;
        request.insert(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".ChannelType"),
                       TELEPATHY_INTERFACE_CHANNEL_TYPE_STREAMED_MEDIA);
        request.insert(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetHandleType"),
                       (uint) HandleTypeContact);
        request.insert(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetHandle"),
                       contact->handle()[0]);

        ConnectionPtr conn = contact->manager()->connection();
        connect(conn->ensureChannel(request),
                SIGNAL(finished(Tp::PendingOperation*)),
                SLOT(onOutgoingChannelCreated(Tp::PendingOperation*)));
    }

    void CallHandler::addIncomingCall(const StreamedMediaChannelPtr &chan)
    {
        mChannels.append(chan);
        connect(chan->becomeReady(),
                SIGNAL(finished(Tp::PendingOperation*)),
                SLOT(onIncomingChannelReady(Tp::PendingOperation*)));
    }

    void CallHandler::onOutgoingChannelCreated(PendingOperation *op)
    {
        if (op->isError()) {
            qWarning() << "CallHandler::onOutgoingChannelCreated: channel cannot be created:" <<
                op->errorName() << "-" << op->errorMessage();

            QMessageBox msgBox;
            msgBox.setText(QString("Unable to call (%1)").arg(op->errorMessage()));
            msgBox.exec();
            return;
        }

        PendingChannel *pc = qobject_cast<PendingChannel *>(op);

        StreamedMediaChannelPtr chan = StreamedMediaChannel::create(pc->connection(),
                pc->objectPath(), pc->immutableProperties());
        mChannels.append(chan);
        connect(chan->becomeReady(),
                SIGNAL(finished(Tp::PendingOperation*)),
                SLOT(onOutgoingChannelReady(Tp::PendingOperation*)));
    }

    void CallHandler::onOutgoingChannelReady(PendingOperation *op)
    {
        PendingReady *pr = qobject_cast<PendingReady *>(op);
        StreamedMediaChannelPtr chan = StreamedMediaChannelPtr(qobject_cast<StreamedMediaChannel *>(pr->object()));

        if (op->isError()) {
            qWarning() << "CallHandler::onOutgoingChannelReady: channel cannot become ready:" <<
                op->errorName() << "-" << op->errorMessage();

            mChannels.removeOne(chan);

            QMessageBox msgBox;
            msgBox.setText(QString("Unable to call (%1)").arg(op->errorMessage()));
            msgBox.exec();
            return;
        }

        ContactManager *cm = chan->connection()->contactManager();
        ContactPtr contact = cm->lookupContactByHandle(chan->targetHandle());
        Q_ASSERT(contact);

        CallWidget *call = new CallWidget(chan, contact);
        mCalls.append(call);
        connect(call,
                SIGNAL(destroyed(QObject *)),
                SLOT(onCallTerminated(QObject *)));
        call->show();
    }

    void CallHandler::onIncomingChannelReady(PendingOperation *op)
    {
        PendingReady *pr = qobject_cast<PendingReady *>(op);
        StreamedMediaChannelPtr chan = StreamedMediaChannelPtr(qobject_cast<StreamedMediaChannel *>(pr->object()));

        if (op->isError()) {
            // ignore - channel cannot be ready
            qWarning() << "CallHandler::onIncomingChannelReady: channel cannot become ready:" <<
                op->errorName() << "-" << op->errorMessage();

            mChannels.removeOne(chan);
            return;
        }

        ContactPtr contact = chan->initiatorContact();

        QMessageBox msgBox;
        msgBox.setText("Incoming call");
        msgBox.setInformativeText(QString("%1 is calling you, do you want to answer?").arg(contact->id()));
        msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
        msgBox.setDefaultButton(QMessageBox::Yes);
        int ret = msgBox.exec();

        if (ret == QMessageBox::No) {
            chan->requestClose();
            return;
        }

        chan->acceptCall();

        CallWidget *call = new CallWidget(chan, contact);
        mCalls.append(call);
        connect(call,
                SIGNAL(destroyed(QObject *)),
                SLOT(onCallTerminated(QObject *)));
        call->show();
    }

    void CallHandler::onCallTerminated(QObject *obj)
    {
        CallWidget *call = (CallWidget *) obj;
        StreamedMediaChannelPtr chan = call->channel();
        mCalls.removeOne(call);
        mChannels.removeOne(chan);
    }