diff options
25 files changed, 518 insertions, 11 deletions
diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp index 1e0e9c2..48ea006 100644 --- a/Swift/Controllers/Chat/ChatsManager.cpp +++ b/Swift/Controllers/Chat/ChatsManager.cpp @@ -43,6 +43,8 @@ #include <Swift/Controllers/SettingConstants.h> #include <Swiften/Client/StanzaChannel.h> #include <Swift/Controllers/WhiteboardManager.h> +#include <Swift/Controllers/ScreenSharing/ScreenSharingController.h> +#include <Swiften/ScreenSharing/IncomingScreenSharing.h> namespace Swift { @@ -70,6 +72,7 @@ ChatsManager::ChatsManager( MUCSearchWindowFactory* mucSearchWindowFactory, ProfileSettingsProvider* profileSettings, FileTransferOverview* ftOverview, + ScreenSharingController* ssController, XMPPRoster* roster, bool eagleMode, SettingsProvider* settings, @@ -82,6 +85,7 @@ ChatsManager::ChatsManager( entityCapsProvider_(entityCapsProvider), mucManager(mucManager), ftOverview_(ftOverview), + ssController_(ssController), roster_(roster), eagleMode_(eagleMode), settings_(settings), @@ -112,6 +116,7 @@ ChatsManager::ChatsManager( mucSearchController_ = new MUCSearchController(jid_, mucSearchWindowFactory, iqRouter, profileSettings_); mucSearchController_->onMUCSelected.connect(boost::bind(&ChatsManager::handleMUCSelectedAfterSearch, this, _1)); ftOverview_->onNewFileTransferController.connect(boost::bind(&ChatsManager::handleNewFileTransferController, this, _1)); + ssController->onNewIncomingScreenSharing.connect(boost::bind(&ChatsManager::handleNewIncomingScreenSharing, this, _1)); whiteboardManager_->onSessionRequest.connect(boost::bind(&ChatsManager::handleWhiteboardSessionRequest, this, _1, _2)); whiteboardManager_->onRequestAccepted.connect(boost::bind(&ChatsManager::handleWhiteboardStateChange, this, _1, ChatWindow::WhiteboardAccepted)); whiteboardManager_->onSessionTerminate.connect(boost::bind(&ChatsManager::handleWhiteboardStateChange, this, _1, ChatWindow::WhiteboardTerminated)); @@ -664,6 +669,13 @@ void ChatsManager::handleNewFileTransferController(FileTransferController* ftc) chatController->activateChatWindow(); } +void ChatsManager::handleNewIncomingScreenSharing(boost::shared_ptr<IncomingScreenSharing> iss) +{ + ChatController* chatController = getChatControllerOrCreate(iss->getSender()); +// chatController->handleNewFileTransferController(ftc); + chatController->activateChatWindow(); +} + void ChatsManager::handleWhiteboardSessionRequest(const JID& contact, bool senderIsSelf) { ChatController* chatController = getChatControllerOrCreate(contact); chatController->handleWhiteboardSessionRequest(senderIsSelf); diff --git a/Swift/Controllers/Chat/ChatsManager.h b/Swift/Controllers/Chat/ChatsManager.h index 5b8b785..31006b0 100644 --- a/Swift/Controllers/Chat/ChatsManager.h +++ b/Swift/Controllers/Chat/ChatsManager.h @@ -50,10 +50,12 @@ namespace Swift { class SettingsProvider; class WhiteboardManager; class HistoryController; + class ScreenSharingController; + class IncomingScreenSharing; class ChatsManager { public: - ChatsManager(JID jid, StanzaChannel* stanzaChannel, IQRouter* iqRouter, EventController* eventController, ChatWindowFactory* chatWindowFactory, JoinMUCWindowFactory* joinMUCWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, PresenceSender* presenceSender, UIEventStream* uiEventStream, ChatListWindowFactory* chatListWindowFactory, bool useDelayForLatency, TimerFactory* timerFactory, MUCRegistry* mucRegistry, EntityCapsProvider* entityCapsProvider, MUCManager* mucManager, MUCSearchWindowFactory* mucSearchWindowFactory, ProfileSettingsProvider* profileSettings, FileTransferOverview* ftOverview, XMPPRoster* roster, bool eagleMode, SettingsProvider* settings, HistoryController* historyController_, WhiteboardManager* whiteboardManager); + ChatsManager(JID jid, StanzaChannel* stanzaChannel, IQRouter* iqRouter, EventController* eventController, ChatWindowFactory* chatWindowFactory, JoinMUCWindowFactory* joinMUCWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, PresenceSender* presenceSender, UIEventStream* uiEventStream, ChatListWindowFactory* chatListWindowFactory, bool useDelayForLatency, TimerFactory* timerFactory, MUCRegistry* mucRegistry, EntityCapsProvider* entityCapsProvider, MUCManager* mucManager, MUCSearchWindowFactory* mucSearchWindowFactory, ProfileSettingsProvider* profileSettings, FileTransferOverview* ftOverview, ScreenSharingController* ssController, XMPPRoster* roster, bool eagleMode, SettingsProvider* settings, HistoryController* historyController_, WhiteboardManager* whiteboardManager); virtual ~ChatsManager(); void setAvatarManager(AvatarManager* avatarManager); void setOnline(bool enabled); @@ -75,6 +77,7 @@ namespace Swift { void handleBookmarksReady(); void handleChatActivity(const JID& jid, const std::string& activity, bool isMUC); void handleNewFileTransferController(FileTransferController*); + void handleNewIncomingScreenSharing(boost::shared_ptr<IncomingScreenSharing> iss); void handleWhiteboardSessionRequest(const JID& contact, bool senderIsSelf); void handleWhiteboardStateChange(const JID& contact, const ChatWindow::WhiteboardSessionState state); void appendRecent(const ChatListWindow::Chat& chat); @@ -130,6 +133,7 @@ namespace Swift { std::list<ChatListWindow::Chat> recentChats_; ProfileSettingsProvider* profileSettings_; FileTransferOverview* ftOverview_; + ScreenSharingController* ssController_; XMPPRoster* roster_; bool eagleMode_; bool userWantsReceipts_; diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp index 581ff31..17dab36 100644 --- a/Swift/Controllers/MainController.cpp +++ b/Swift/Controllers/MainController.cpp @@ -78,6 +78,7 @@ #include <Swiften/Client/ClientXMLTracer.h> #include <Swift/Controllers/SettingConstants.h> #include <Swiften/Client/StanzaChannel.h> +#include "Swift/Controllers/ScreenSharing/ScreenSharingController.h" namespace Swift { @@ -109,7 +110,8 @@ MainController::MainController( idleDetector_(idleDetector), loginWindow_(NULL) , useDelayForLatency_(useDelayForLatency), - ftOverview_(NULL) { + ftOverview_(NULL), + ssController_(NULL) { storages_ = NULL; certificateStorage_ = NULL; statusTracker_ = NULL; @@ -237,6 +239,8 @@ void MainController::resetClient() { #endif delete ftOverview_; ftOverview_ = NULL; + delete ssController_; + ssController_ = NULL; delete rosterController_; rosterController_ = NULL; delete eventNotifier_; @@ -302,7 +306,8 @@ void MainController::handleConnected() { client_->getFileTransferManager()->startListeningOnPort(randomPort); ftOverview_ = new FileTransferOverview(client_->getFileTransferManager()); fileTransferListController_->setFileTransferOverview(ftOverview_); - rosterController_ = new RosterController(jid_, client_->getRoster(), client_->getAvatarManager(), uiFactory_, client_->getNickManager(), client_->getNickResolver(), client_->getPresenceOracle(), client_->getSubscriptionManager(), eventController_, uiEventStream_, client_->getIQRouter(), settings_, client_->getEntityCapsProvider(), ftOverview_); + ssController_ = new ScreenSharingController(client_->getScreenSharingManager(), uiFactory_, networkFactories_->getTimerFactory()); + rosterController_ = new RosterController(jid_, client_->getRoster(), client_->getAvatarManager(), uiFactory_, client_->getNickManager(), client_->getNickResolver(), client_->getPresenceOracle(), client_->getSubscriptionManager(), eventController_, uiEventStream_, client_->getIQRouter(), settings_, client_->getEntityCapsProvider(), ftOverview_, ssController_); rosterController_->onChangeStatusRequest.connect(boost::bind(&MainController::handleChangeStatusRequest, this, _1, _2)); rosterController_->onSignOutRequest.connect(boost::bind(&MainController::signOut, this)); rosterController_->getWindow()->onShowCertificateRequest.connect(boost::bind(&MainController::handleShowCertificateRequest, this)); @@ -320,7 +325,7 @@ void MainController::handleConnected() { historyViewController_ = new HistoryViewController(jid_, uiEventStream_, historyController_, client_->getNickResolver(), client_->getAvatarManager(), client_->getPresenceOracle(), uiFactory_); chatsManager_ = new ChatsManager(jid_, client_->getStanzaChannel(), client_->getIQRouter(), eventController_, uiFactory_, uiFactory_, client_->getNickResolver(), client_->getPresenceOracle(), client_->getPresenceSender(), uiEventStream_, uiFactory_, useDelayForLatency_, networkFactories_->getTimerFactory(), client_->getMUCRegistry(), client_->getEntityCapsProvider(), client_->getMUCManager(), uiFactory_, profileSettings_, ftOverview_, client_->getRoster(), !settings_->getSetting(SettingConstants::REMEMBER_RECENT_CHATS), settings_, historyController_, whiteboardManager_); #else - chatsManager_ = new ChatsManager(jid_, client_->getStanzaChannel(), client_->getIQRouter(), eventController_, uiFactory_, uiFactory_, client_->getNickResolver(), client_->getPresenceOracle(), client_->getPresenceSender(), uiEventStream_, uiFactory_, useDelayForLatency_, networkFactories_->getTimerFactory(), client_->getMUCRegistry(), client_->getEntityCapsProvider(), client_->getMUCManager(), uiFactory_, profileSettings_, ftOverview_, client_->getRoster(), !settings_->getSetting(SettingConstants::REMEMBER_RECENT_CHATS), settings_, NULL, whiteboardManager_); + chatsManager_ = new ChatsManager(jid_, client_->getStanzaChannel(), client_->getIQRouter(), eventController_, uiFactory_, uiFactory_, client_->getNickResolver(), client_->getPresenceOracle(), client_->getPresenceSender(), uiEventStream_, uiFactory_, useDelayForLatency_, networkFactories_->getTimerFactory(), client_->getMUCRegistry(), client_->getEntityCapsProvider(), client_->getMUCManager(), uiFactory_, profileSettings_, ftOverview_, ssController_, client_->getRoster(), !settings_->getSetting(SettingConstants::REMEMBER_RECENT_CHATS), settings_, NULL, whiteboardManager_); #endif client_->onMessageReceived.connect(boost::bind(&ChatsManager::handleIncomingMessage, chatsManager_, _1)); @@ -340,6 +345,10 @@ void MainController::handleConnected() { discoInfo.addFeature(DiscoInfo::JingleFTFeature); discoInfo.addFeature(DiscoInfo::JingleTransportsIBBFeature); discoInfo.addFeature(DiscoInfo::JingleTransportsS5BFeature); + // Screen sharing + discoInfo.addFeature(DiscoInfo::JingleRTPFeature); + discoInfo.addFeature(DiscoInfo::JingleTransportRawUDPFeature); + discoInfo.addFeature(DiscoInfo::JingleScreenSharingFeature); #endif #ifdef SWIFT_EXPERIMENTAL_WB discoInfo.addFeature(DiscoInfo::WhiteboardFeature); diff --git a/Swift/Controllers/MainController.h b/Swift/Controllers/MainController.h index 2e5bd05..ad8fef2 100644 --- a/Swift/Controllers/MainController.h +++ b/Swift/Controllers/MainController.h @@ -71,6 +71,7 @@ namespace Swift { class AdHocCommandWindowFactory; class FileTransferOverview; class WhiteboardManager; + class ScreenSharingController; class MainController { public: @@ -176,5 +177,6 @@ namespace Swift { static const int SecondsToWaitBeforeForceQuitting; FileTransferOverview* ftOverview_; WhiteboardManager* whiteboardManager_; + ScreenSharingController* ssController_; }; } diff --git a/Swift/Controllers/Roster/ContactRosterItem.h b/Swift/Controllers/Roster/ContactRosterItem.h index 8389a44..d156b1f 100644 --- a/Swift/Controllers/Roster/ContactRosterItem.h +++ b/Swift/Controllers/Roster/ContactRosterItem.h @@ -26,6 +26,7 @@ class ContactRosterItem : public RosterItem { enum Feature { FileTransferFeature, WhiteboardFeature, + ScreenSharingFeature, }; public: diff --git a/Swift/Controllers/Roster/RosterController.cpp b/Swift/Controllers/Roster/RosterController.cpp index ec52993..40fd957 100644 --- a/Swift/Controllers/Roster/RosterController.cpp +++ b/Swift/Controllers/Roster/RosterController.cpp @@ -36,6 +36,7 @@ #include "Swift/Controllers/UIEvents/RenameRosterItemUIEvent.h" #include "Swift/Controllers/UIEvents/RenameGroupUIEvent.h" #include "Swift/Controllers/UIEvents/SendFileUIEvent.h" +#include "Swift/Controllers/UIEvents/ShareScreenUIEvent.h" #include <Swiften/FileTransfer/FileTransferManager.h> #include <Swiften/Client/NickManager.h> #include <Swift/Controllers/Intl.h> @@ -44,14 +45,15 @@ #include <Swiften/Disco/EntityCapsManager.h> #include <Swiften/Jingle/JingleSessionManager.h> #include <Swift/Controllers/SettingConstants.h> +#include "Swift/Controllers/ScreenSharing/ScreenSharingController.h" namespace Swift { /** * The controller does not gain ownership of these parameters. */ -RosterController::RosterController(const JID& jid, XMPPRoster* xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickManager* nickManager, NickResolver* nickResolver, PresenceOracle* presenceOracle, SubscriptionManager* subscriptionManager, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter, SettingsProvider* settings, EntityCapsProvider* entityCapsManager, FileTransferOverview* fileTransferOverview) - : myJID_(jid), xmppRoster_(xmppRoster), mainWindowFactory_(mainWindowFactory), mainWindow_(mainWindowFactory_->createMainWindow(uiEventStream)), roster_(new Roster()), offlineFilter_(new OfflineRosterFilter()), nickManager_(nickManager), nickResolver_(nickResolver), uiEventStream_(uiEventStream), entityCapsManager_(entityCapsManager), ftOverview_(fileTransferOverview) { +RosterController::RosterController(const JID& jid, XMPPRoster* xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickManager* nickManager, NickResolver* nickResolver, PresenceOracle* presenceOracle, SubscriptionManager* subscriptionManager, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter, SettingsProvider* settings, EntityCapsProvider* entityCapsManager, FileTransferOverview* fileTransferOverview, ScreenSharingController *ssController) + : myJID_(jid), xmppRoster_(xmppRoster), mainWindowFactory_(mainWindowFactory), mainWindow_(mainWindowFactory_->createMainWindow(uiEventStream)), roster_(new Roster()), offlineFilter_(new OfflineRosterFilter()), nickManager_(nickManager), nickResolver_(nickResolver), uiEventStream_(uiEventStream), entityCapsManager_(entityCapsManager), ftOverview_(fileTransferOverview), ssController_(ssController) { assert(fileTransferOverview); iqRouter_ = iqRouter; presenceOracle_ = presenceOracle; @@ -238,6 +240,10 @@ void RosterController::handleUIEvent(boost::shared_ptr<UIEvent> event) { //TODO add send file dialog to ChatView of receipient jid ftOverview_->sendFile(sendFileEvent->getJID(), sendFileEvent->getFilename()); } + else if (boost::shared_ptr<ShareScreenUIEvent> shareScreenEvent = boost::dynamic_pointer_cast<ShareScreenUIEvent>(event)) { + std::cout << "Create sharing: " << ssController_->createOugoingScreenSharing(shareScreenEvent->jid); + std::cout << std::endl; + } } void RosterController::setContactGroups(const JID& jid, const std::vector<std::string>& groups) { @@ -324,6 +330,12 @@ void RosterController::handleOnCapsChanged(const JID& jid) { if (info->hasFeature(DiscoInfo::WhiteboardFeature)) { features.insert(ContactRosterItem::WhiteboardFeature); } + if (info->hasFeature(DiscoInfo::JingleFeature) + && info->hasFeature(DiscoInfo::JingleRTPFeature) + && info->hasFeature(DiscoInfo::JingleTransportRawUDPFeature) + && info->hasFeature(DiscoInfo::JingleScreenSharingFeature)) { + features.insert(ContactRosterItem::ScreenSharingFeature); + } roster_->setAvailableFeatures(jid, features); } } diff --git a/Swift/Controllers/Roster/RosterController.h b/Swift/Controllers/Roster/RosterController.h index 5e40124..2fb642d 100644 --- a/Swift/Controllers/Roster/RosterController.h +++ b/Swift/Controllers/Roster/RosterController.h @@ -39,10 +39,11 @@ namespace Swift { class NickManager; class EntityCapsProvider; class FileTransferManager; + class ScreenSharingController; class RosterController { public: - RosterController(const JID& jid, XMPPRoster* xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickManager* nickManager, NickResolver* nickResolver, PresenceOracle* presenceOracle, SubscriptionManager* subscriptionManager, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter_, SettingsProvider* settings, EntityCapsProvider* entityCapsProvider, FileTransferOverview* fileTransferOverview); + RosterController(const JID& jid, XMPPRoster* xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickManager* nickManager, NickResolver* nickResolver, PresenceOracle* presenceOracle, SubscriptionManager* subscriptionManager, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter_, SettingsProvider* settings, EntityCapsProvider* entityCapsProvider, FileTransferOverview* fileTransferOverview, ScreenSharingController* ssController); ~RosterController(); void showRosterWindow(); MainWindow* getWindow() {return mainWindow_;}; @@ -94,6 +95,7 @@ namespace Swift { UIEventStream* uiEventStream_; EntityCapsProvider* entityCapsManager_; FileTransferOverview* ftOverview_; + ScreenSharingController* ssController_; boost::bsignals::scoped_connection changeStatusConnection_; boost::bsignals::scoped_connection signOutConnection_; diff --git a/Swift/Controllers/SConscript b/Swift/Controllers/SConscript index 7cd017b..2dba9a9 100644 --- a/Swift/Controllers/SConscript +++ b/Swift/Controllers/SConscript @@ -74,7 +74,8 @@ if env["SCONS_STAGE"] == "build" : "XMPPURIController.cpp", "ChatMessageSummarizer.cpp", "SettingConstants.cpp", - "WhiteboardManager.cpp" + "WhiteboardManager.cpp", + "ScreenSharing/ScreenSharingController.cpp", ]) env.Append(UNITTEST_SOURCES = [ diff --git a/Swift/Controllers/ScreenSharing/DesktopScreenGrabber.h b/Swift/Controllers/ScreenSharing/DesktopScreenGrabber.h new file mode 100644 index 0000000..4fac6fe --- /dev/null +++ b/Swift/Controllers/ScreenSharing/DesktopScreenGrabber.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2012 Yoann Blein + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +namespace Swift { + class Image; + + class DesktopScreenGrabber { + public: + virtual ~DesktopScreenGrabber() {} + + virtual Image grab() const = 0; + }; +} diff --git a/Swift/Controllers/ScreenSharing/ScreenSharingController.cpp b/Swift/Controllers/ScreenSharing/ScreenSharingController.cpp new file mode 100644 index 0000000..fd3357d --- /dev/null +++ b/Swift/Controllers/ScreenSharing/ScreenSharingController.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2012 Yoann Blein + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "ScreenSharingController.h" + +#include <Swiften/ScreenSharing/ScreenSharingManager.h> +#include <Swiften/ScreenSharing/IncomingScreenSharing.h> +#include <Swiften/ScreenSharing/OutgoingScreenSharing.h> +#include <Swiften/ScreenSharing/Image.h> +#include <Swiften/Network/TimerFactory.h> +#include <Swiften/Network/Timer.h> +#include "Swift/QtUI/ScreenSharing/QtDesktopScreenGrabber.h" +#include "Swift/Controllers/UIInterfaces/RemoteScreenWindowFactory.h" +#include "Swift/Controllers/UIInterfaces/RemoteScreenWindow.h" + +#include <boost/bind.hpp> + +namespace Swift { + +ScreenSharingController::ScreenSharingController(ScreenSharingManager *screenSharingManager, RemoteScreenWindowFactory* remoteScreenViewerFactory, TimerFactory* timerFactory) + : screenSharingManager(screenSharingManager), remoteScreenWindowFactory(remoteScreenViewerFactory), remoteScreenWindow(0), + grabTimer(timerFactory->createTimer(500)), screenGrabber(new QtDesktopScreenGrabber) +{ + screenSharingManager->onIncomingScreenSharing.connect(boost::bind(&ScreenSharingController::handleIncomingScreenSharing, this, _1)); + grabTimer->onTick.connect(boost::bind(&ScreenSharingController::handleGrabTimerTick, this)); +} + +ScreenSharingController::~ScreenSharingController() +{ + grabTimer->onTick.disconnect(boost::bind(&ScreenSharingController::handleGrabTimerTick, this)); + delete remoteScreenWindow; +} + +boost::shared_ptr<OutgoingScreenSharing> ScreenSharingController::createOugoingScreenSharing(const JID& to) +{ + if (!oss) { + oss = screenSharingManager->createOutgoingScreenSharing(to); + if (oss) { + oss->onReady.connect(boost::bind(&ScreenSharingController::handleOssReady, this)); + oss->onFinished.connect(boost::bind(&ScreenSharingController::handleOutgoingFinished, this)); + const Image& image = screenGrabber->grab(); + oss->start(image.width, image.height); + } + return oss; + } + return boost::shared_ptr<OutgoingScreenSharing>(); +} + +void ScreenSharingController::handleIncomingScreenSharing(boost::shared_ptr<IncomingScreenSharing> incomingScreenSharing) +{ + if (iss) { + incomingScreenSharing->cancel(); + } else { + iss = incomingScreenSharing; + iss->accept(); + iss->onFinished.connect(boost::bind(&ScreenSharingController::handleIncomingFinished, this)); + remoteScreenWindow = remoteScreenWindowFactory->createRemoteScreenViewer(iss); +// onNewIncomingScreenSharing(iss); + } +} + +void ScreenSharingController::handleGrabTimerTick() +{ + if (oss) { + grabTimer->start(); + oss->addImage(screenGrabber->grab()); + } +} + +void ScreenSharingController::handleOssReady() +{ + handleGrabTimerTick(); +} + +void ScreenSharingController::handleIncomingFinished() +{ + iss->onFinished.disconnect(boost::bind(&ScreenSharingController::handleIncomingFinished, this)); + iss.reset(); + delete remoteScreenWindow; + remoteScreenWindow = 0; +} + +void ScreenSharingController::handleOutgoingFinished() +{ + oss->onReady.disconnect(boost::bind(&ScreenSharingController::handleOssReady, this)); + oss->onFinished.disconnect(boost::bind(&ScreenSharingController::handleOutgoingFinished, this)); + oss.reset(); +} + +} diff --git a/Swift/Controllers/ScreenSharing/ScreenSharingController.h b/Swift/Controllers/ScreenSharing/ScreenSharingController.h new file mode 100644 index 0000000..6bae132 --- /dev/null +++ b/Swift/Controllers/ScreenSharing/ScreenSharingController.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2012 Yoann Blein + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swiften/Base/boost_bsignals.h> + +#include <boost/shared_ptr.hpp> + +namespace Swift { + class ScreenSharingManager; + class IncomingScreenSharing; + class OutgoingScreenSharing; + class Timer; + class TimerFactory; + class DesktopScreenGrabber; + class RemoteScreenWindowFactory; + class RemoteScreenWindow; + class JID; + + class ScreenSharingController { + public: + ScreenSharingController(ScreenSharingManager* screenSharingManager, RemoteScreenWindowFactory* remoteScreenWindowFactory, TimerFactory* timerFactory); + ~ScreenSharingController(); + + boost::shared_ptr<OutgoingScreenSharing> createOugoingScreenSharing(const JID& to); + + public: + boost::signal<void (boost::shared_ptr<IncomingScreenSharing>)> onNewIncomingScreenSharing; + + private: + void handleIncomingScreenSharing(boost::shared_ptr<IncomingScreenSharing> incomingScreenSharing); + void handleGrabTimerTick(); + void handleOssReady(); + void handleIncomingFinished(); + void handleOutgoingFinished(); + + private: + ScreenSharingManager* screenSharingManager; + RemoteScreenWindowFactory* remoteScreenWindowFactory; + + RemoteScreenWindow* remoteScreenWindow; + boost::shared_ptr<Timer> grabTimer; + DesktopScreenGrabber* screenGrabber; + boost::shared_ptr<IncomingScreenSharing> iss; + boost::shared_ptr<OutgoingScreenSharing> oss; + }; +} diff --git a/Swift/Controllers/UIEvents/ShareScreenUIEvent.h b/Swift/Controllers/UIEvents/ShareScreenUIEvent.h new file mode 100644 index 0000000..de2b670 --- /dev/null +++ b/Swift/Controllers/UIEvents/ShareScreenUIEvent.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2012 Yoann Blein + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swiften/JID/JID.h> +#include <Swift/Controllers/UIEvents/UIEvent.h> + +#include <boost/shared_ptr.hpp> + +namespace Swift { + class ShareScreenUIEvent : public UIEvent { + public: + typedef boost::shared_ptr<SendFileUIEvent> ref; + + ShareScreenUIEvent(const JID& jid) : jid(jid) {} + + public: + JID jid; + }; +} diff --git a/Swift/Controllers/UIInterfaces/RemoteScreenWindow.h b/Swift/Controllers/UIInterfaces/RemoteScreenWindow.h new file mode 100644 index 0000000..c31ca91 --- /dev/null +++ b/Swift/Controllers/UIInterfaces/RemoteScreenWindow.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2012 Yoann Blein + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +namespace Swift { + class IncomingScreenSharing; + class Image; + + class RemoteScreenWindow { + public: + RemoteScreenWindow(boost::shared_ptr<IncomingScreenSharing> incScreenSharing) + : iss(incScreenSharing) {} + virtual ~RemoteScreenWindow() {} + + protected: + boost::shared_ptr<IncomingScreenSharing> iss; + }; +} diff --git a/Swift/Controllers/UIInterfaces/RemoteScreenWindowFactory.h b/Swift/Controllers/UIInterfaces/RemoteScreenWindowFactory.h new file mode 100644 index 0000000..7c78777 --- /dev/null +++ b/Swift/Controllers/UIInterfaces/RemoteScreenWindowFactory.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2012 Yoann Blein + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include "Swift/Controllers/UIInterfaces/RemoteScreenWindow.h" + +#include <boost/shared_ptr.hpp> + +namespace Swift { + class IncomingScreenSharing; + class RemoteScreenWindowFactory { + public: + virtual ~RemoteScreenWindowFactory() {} + + virtual RemoteScreenWindow* createRemoteScreenViewer(boost::shared_ptr<IncomingScreenSharing> iss) = 0; + }; +} diff --git a/Swift/Controllers/UIInterfaces/UIFactory.h b/Swift/Controllers/UIInterfaces/UIFactory.h index 6b4efd8..e0e5425 100644 --- a/Swift/Controllers/UIInterfaces/UIFactory.h +++ b/Swift/Controllers/UIInterfaces/UIFactory.h @@ -21,12 +21,12 @@ #include <Swift/Controllers/UIInterfaces/AdHocCommandWindowFactory.h> #include <Swift/Controllers/UIInterfaces/FileTransferListWidgetFactory.h> #include <Swift/Controllers/UIInterfaces/WhiteboardWindowFactory.h> +#include <Swift/Controllers/UIInterfaces/RemoteScreenWindowFactory.h> namespace Swift { class UIFactory : public ChatListWindowFactory, public ChatWindowFactory, - public HistoryWindowFactory, public EventWindowFactory, public LoginWindowFactory, public MainWindowFactory, @@ -38,7 +38,8 @@ namespace Swift { public ContactEditWindowFactory, public AdHocCommandWindowFactory, public FileTransferListWidgetFactory, - public WhiteboardWindowFactory { + public WhiteboardWindowFactory, + public RemoteScreenWindowFactory { public: virtual ~UIFactory() {} }; diff --git a/Swift/QtUI/QtUIFactory.cpp b/Swift/QtUI/QtUIFactory.cpp index a154fb0..ba9cbc9 100644 --- a/Swift/QtUI/QtUIFactory.cpp +++ b/Swift/QtUI/QtUIFactory.cpp @@ -26,6 +26,7 @@ #include "QtAdHocCommandWindow.h" #include "QtFileTransferListWidget.h" #include "Whiteboard/QtWhiteboardWindow.h" +#include <Swift/QtUI/ScreenSharing/QtRemoteScreenWindow.h> #include <Swift/Controllers/Settings/SettingsProviderHierachy.h> #include <Swift/QtUI/QtUISettingConstants.h> #include <QtHistoryWindow.h> @@ -77,6 +78,13 @@ FileTransferListWidget* QtUIFactory::createFileTransferListWidget() { return widget; } +RemoteScreenWindow* QtUIFactory::createRemoteScreenViewer(boost::shared_ptr<IncomingScreenSharing> iss) +{ + QtRemoteScreenWindow* rsv = new QtRemoteScreenWindow(iss); + rsv->show(); + return rsv; +} + MainWindow* QtUIFactory::createMainWindow(UIEventStream* eventStream) { lastMainWindow = new QtMainWindow(settings, eventStream, loginWindow->getMenus(), emoticonsExist_); return lastMainWindow; diff --git a/Swift/QtUI/QtUIFactory.h b/Swift/QtUI/QtUIFactory.h index 30f0101..8d4be81 100644 --- a/Swift/QtUI/QtUIFactory.h +++ b/Swift/QtUI/QtUIFactory.h @@ -46,6 +46,7 @@ namespace Swift { virtual ContactEditWindow* createContactEditWindow(); virtual FileTransferListWidget* createFileTransferListWidget(); virtual WhiteboardWindow* createWhiteboardWindow(boost::shared_ptr<WhiteboardSession> whiteboardSession); + virtual RemoteScreenWindow* createRemoteScreenViewer(boost::shared_ptr<IncomingScreenSharing> iss); virtual void createAdHocCommandWindow(boost::shared_ptr<OutgoingAdHocCommandSession> command); private slots: diff --git a/Swift/QtUI/Roster/QtRosterWidget.cpp b/Swift/QtUI/Roster/QtRosterWidget.cpp index 1cf073b..0e75057 100644 --- a/Swift/QtUI/Roster/QtRosterWidget.cpp +++ b/Swift/QtUI/Roster/QtRosterWidget.cpp @@ -16,6 +16,7 @@ #include "Swift/Controllers/UIEvents/RenameGroupUIEvent.h" #include "Swift/Controllers/UIEvents/SendFileUIEvent.h" #include "Swift/Controllers/UIEvents/RequestWhiteboardUIEvent.h" +#include "Swift/Controllers/UIEvents/ShareScreenUIEvent.h" #include "QtContactEditWindow.h" #include "Swift/Controllers/Roster/ContactRosterItem.h" #include "Swift/Controllers/Roster/GroupRosterItem.h" @@ -62,6 +63,10 @@ void QtRosterWidget::contextMenuEvent(QContextMenuEvent* event) { if (contact->supportsFeature(ContactRosterItem::FileTransferFeature)) { sendFile = contextMenu.addAction(tr("Send File")); } + QAction* shareScreen = NULL; + if (contact->supportsFeature(ContactRosterItem::ScreenSharingFeature)) { + shareScreen = contextMenu.addAction(tr("Share my screen")); + } #endif #ifdef SWIFT_EXPERIMENTAL_WB QAction* startWhiteboardChat = NULL; @@ -85,6 +90,9 @@ void QtRosterWidget::contextMenuEvent(QContextMenuEvent* event) { eventStream_->send(boost::make_shared<SendFileUIEvent>(contact->getJID(), Q2PSTRING(fileName))); } } + else if (shareScreen && result == shareScreen) { + eventStream_->send(boost::make_shared<ShareScreenUIEvent>(contact->getJID())); + } #endif #ifdef SWIFT_EXPERIMENTAL_WB else if (startWhiteboardChat && result == startWhiteboardChat) { diff --git a/Swift/QtUI/SConscript b/Swift/QtUI/SConscript index c940d49..9d8f42b 100644 --- a/Swift/QtUI/SConscript +++ b/Swift/QtUI/SConscript @@ -161,7 +161,10 @@ sources = [ "QtChatWindowJSBridge.cpp", "QtMUCConfigurationWindow.cpp", "QtAffiliationEditor.cpp", - "QtUISettingConstants.cpp" + "QtUISettingConstants.cpp", + "ScreenSharing/RemoteScreenViewerWidget.cpp", + "ScreenSharing/QtRemoteScreenWindow.cpp", + "ScreenSharing/QtDesktopScreenGrabber.cpp", ] myenv["SWIFT_VERSION"] = Version.getBuildVersion(env.Dir("#").abspath, "swift") diff --git a/Swift/QtUI/ScreenSharing/QtDesktopScreenGrabber.cpp b/Swift/QtUI/ScreenSharing/QtDesktopScreenGrabber.cpp new file mode 100644 index 0000000..a5eeafd --- /dev/null +++ b/Swift/QtUI/ScreenSharing/QtDesktopScreenGrabber.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2012 Yoann Blein + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "QtDesktopScreenGrabber.h" + +#include <QImage> +#include <QPixmap> +#include <QApplication> +#include <QDesktopWidget> + +#include <Swiften/ScreenSharing/Image.h> + +/*#include <QImage> +#include <QLabel>*/ + +namespace Swift { + +QtDesktopScreenGrabber::QtDesktopScreenGrabber() +{ + /*Image img = grab(); + QImage qImg(img.data.data(), img.width, img.height, QImage::Format_RGB888); + QLabel *label = new QLabel; + label->setPixmap(QPixmap::fromImage(qImg)); + label->show();*/ +} + +QtDesktopScreenGrabber::~QtDesktopScreenGrabber() +{ +} + +Image QtDesktopScreenGrabber::grab() const +{ + QImage qImg = QPixmap::grabWindow(QApplication::desktop()->winId()).toImage().convertToFormat(QImage::Format_RGB888); + return Image(qImg.width(), qImg.height(), qImg.constBits()); +} + +} diff --git a/Swift/QtUI/ScreenSharing/QtDesktopScreenGrabber.h b/Swift/QtUI/ScreenSharing/QtDesktopScreenGrabber.h new file mode 100644 index 0000000..55a7842 --- /dev/null +++ b/Swift/QtUI/ScreenSharing/QtDesktopScreenGrabber.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2012 Yoann Blein + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include "Swift/Controllers/ScreenSharing/DesktopScreenGrabber.h" + +namespace Swift { + class QtDesktopScreenGrabber : public DesktopScreenGrabber { + public: + QtDesktopScreenGrabber(); + virtual ~QtDesktopScreenGrabber(); + + virtual Image grab() const; + }; +} diff --git a/Swift/QtUI/ScreenSharing/QtRemoteScreenWindow.cpp b/Swift/QtUI/ScreenSharing/QtRemoteScreenWindow.cpp new file mode 100644 index 0000000..e6cd291 --- /dev/null +++ b/Swift/QtUI/ScreenSharing/QtRemoteScreenWindow.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2012 Yoann Blein + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "QtRemoteScreenWindow.h" +#include "RemoteScreenViewerWidget.h" + +#include <QToolBar> + +#include <Swiften/ScreenSharing/IncomingScreenSharing.h> + +namespace Swift { + +QtRemoteScreenWindow::QtRemoteScreenWindow(boost::shared_ptr<IncomingScreenSharing> incScreenSharing, QWidget *parent) + : QMainWindow(parent), RemoteScreenWindow(incScreenSharing) +{ + setCentralWidget(new RemoteScreenViewerWidget(iss)); + + controlToolBar = addToolBar(tr("Control")); + closeAction = controlToolBar->addAction(QIcon::fromTheme("window-close"), tr("&Terminate session"), this, SLOT(handleCloseTriggered())); +} + +QtRemoteScreenWindow::~QtRemoteScreenWindow() +{ +} + +void QtRemoteScreenWindow::handleCloseTriggered() +{ + iss->stop(); +} + +} diff --git a/Swift/QtUI/ScreenSharing/QtRemoteScreenWindow.h b/Swift/QtUI/ScreenSharing/QtRemoteScreenWindow.h new file mode 100644 index 0000000..00ac803 --- /dev/null +++ b/Swift/QtUI/ScreenSharing/QtRemoteScreenWindow.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2012 Yoann Blein + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include "Swift/Controllers/UIInterfaces/RemoteScreenWindow.h" + +#include <QMainWindow> + +class QToolBar; + +namespace Swift { + + class QtRemoteScreenWindow : public QMainWindow, public RemoteScreenWindow { + Q_OBJECT + + public: + QtRemoteScreenWindow(boost::shared_ptr<IncomingScreenSharing> incScreenSharing, QWidget *parent = 0); + virtual ~QtRemoteScreenWindow(); + + private slots: + void handleCloseTriggered(); + + private: + QAction* closeAction; + QToolBar* controlToolBar; + }; +} diff --git a/Swift/QtUI/ScreenSharing/RemoteScreenViewerWidget.cpp b/Swift/QtUI/ScreenSharing/RemoteScreenViewerWidget.cpp new file mode 100644 index 0000000..f601f1b --- /dev/null +++ b/Swift/QtUI/ScreenSharing/RemoteScreenViewerWidget.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2012 Yoann Blein + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "RemoteScreenViewerWidget.h" + +#include <QResizeEvent> +#include <QPainter> + +#include <boost/bind.hpp> + +#include <Swiften/ScreenSharing/IncomingScreenSharing.h> +#include <Swiften/ScreenSharing/Image.h> + + +namespace Swift { + +RemoteScreenViewerWidget::RemoteScreenViewerWidget(boost::shared_ptr<IncomingScreenSharing> incScreenSharing, QWidget *parent) : + QWidget(parent), iss(incScreenSharing) +{ + iss->onNewImageReceived.connect(boost::bind(&RemoteScreenViewerWidget::handleNewImageReceived, this, _1)); +} + +RemoteScreenViewerWidget::~RemoteScreenViewerWidget() +{ + iss->onNewImageReceived.disconnect(boost::bind(&RemoteScreenViewerWidget::handleNewImageReceived, this, _1)); +} + +void RemoteScreenViewerWidget::paintEvent(QPaintEvent *) +{ + QPainter painter(this); + if (!pixmap.isNull()) { + painter.translate(geometry().center()); + painter.drawPixmap(-pixmap.rect().center(), pixmap); + } +} + +void RemoteScreenViewerWidget::resizeEvent(QResizeEvent *event) +{ + if (!pixmap.isNull()) + pixmap = pixmap.scaled(event->size(), Qt::KeepAspectRatio); + QWidget::resizeEvent(event); +} + +void RemoteScreenViewerWidget::handleNewImageReceived(const Image& image) +{ + QImage qImg(image.data.data(), image.width, image.height, QImage::Format_RGB888); + pixmap = QPixmap::fromImage(qImg).scaled(size(), Qt::KeepAspectRatio); + update(); +} + +} diff --git a/Swift/QtUI/ScreenSharing/RemoteScreenViewerWidget.h b/Swift/QtUI/ScreenSharing/RemoteScreenViewerWidget.h new file mode 100644 index 0000000..622bd26 --- /dev/null +++ b/Swift/QtUI/ScreenSharing/RemoteScreenViewerWidget.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2012 Yoann Blein + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <QWidget> + +#include <boost/shared_ptr.hpp> + +namespace Swift { + class IncomingScreenSharing; + class Image; + + class RemoteScreenViewerWidget : public QWidget { + Q_OBJECT + public: + RemoteScreenViewerWidget(boost::shared_ptr<IncomingScreenSharing> incScreenSharing, QWidget *parent = 0); + ~RemoteScreenViewerWidget(); + + protected: + void paintEvent(QPaintEvent *); + void resizeEvent(QResizeEvent *event); + + private: + void handleNewImageReceived(const Image& image); + + private: + boost::shared_ptr<IncomingScreenSharing> iss; + QPixmap pixmap; + }; +} |