From 4d522589c0ab04ae2be76d53788597626e57e71f Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 22 Jul 2014 14:35:30 +0200 Subject: Bugfix: One click source change now fully supported Since the async nature of this protocol introduces race conditions when changing the source of the projection, the possiblity that two servers exist at a moment is still there. Even though we thought we do not support multiple sources. This is the reason why _desiredProjectionSource is needed after all. --- src/server/mainwindow/mainwindow.cpp | 130 +++++++++++++++-------------------- 1 file changed, 55 insertions(+), 75 deletions(-) (limited to 'src/server/mainwindow/mainwindow.cpp') diff --git a/src/server/mainwindow/mainwindow.cpp b/src/server/mainwindow/mainwindow.cpp index d7cab75..ab94535 100644 --- a/src/server/mainwindow/mainwindow.cpp +++ b/src/server/mainwindow/mainwindow.cpp @@ -316,8 +316,7 @@ void MainWindow::tellClientCurrentSituation(Client* client) client->lockScreen(true); if (_mode == Mode::Broadcast){ - // _watchers.insert(client->id(), client); - client->setWatcher(true); + client->setDesiredProjectionSource(_streamingSource); Client* c = getClientFromId(_streamingSource); if (c != NULL) { client->startVncClient(c); @@ -660,8 +659,10 @@ void MainWindow::onButtonTutorToAll() // Set all clients as watchers for (QList::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it) { - if ((*it)->client() != NULL && (*it)->client() != getClientFromId(_streamingSource)) - (*it)->client()->setWatcher(true); + if ((*it)->client() != NULL && (*it)->client() != getClientFromId(_streamingSource)){ + (*it)->client()->setDesiredProjectionSource(getTutorFrame()->client()->id()); + } + } } else // If this mode is already active @@ -702,25 +703,21 @@ void MainWindow::onButtonTutorToStudent() // If this is the first call in this mode clear the watchers if (_mode != Mode::Multicast) { - // _watchers.clear(); for (QList::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it) { if ((*it)->client() != NULL) - (*it)->client()->setWatcher(false); + (*it)->client()->setDesiredProjectionSource(NO_SOURCE); } } // If "to" already watches "from" stop it - // if (_watchers.contains(to->id())) - if (getClientFromId(getSelectedFrame()->client()->id())->isWatcher()) + if (getSelectedFrame()->client()->isWatcher()) { - // _watchers.remove(to->id()); - getClientFromId(getSelectedFrame()->client()->id())->setWatcher(false); + getSelectedFrame()->client()->setDesiredProjectionSource(NO_SOURCE); } else // list "to" as watcher { - // _watchers.insert(to->id(), to); - getClientFromId(getSelectedFrame()->client()->id())->setWatcher(true); + getSelectedFrame()->client()->setDesiredProjectionSource(getTutorFrame()->client()->id()); } _mode = Mode::Multicast; @@ -746,31 +743,25 @@ void MainWindow::onButtonStudentToTutor() QMessageBox::critical(this, tr("Projection"), sStrSourceOffline); else if (getTutorFrame()->client() == NULL) QMessageBox::critical(this, tr("Projection"), sStrTutorOffline); - else{ - DisableButtons(); - - if (_mode != Mode::Unicast) - { - // If this is the first run in this mode set the tutor as watcher - for (QList::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it) - if ((*it)->client() != NULL) - (*it)->client()->setWatcher(getTutorFrame()->client()->id() == (*it)->client()->id()); - _mode = Mode::Unicast; - } - else + else + { + // If this is not the first run in this mode and the current source is selected, stop the streaming. + if (_mode == Mode::Unicast && getSelectedFrame()->client()->id() == _streamingSource) { - // If this mode is already active and the current source is selected, stop the streaming. - if (getSelectedFrame()->client()->id() == _streamingSource ) - { - // Stop reset everything - _mode = Mode::None; - reset(); - return; - } - // If another client is selected solely the current streaming source shall be changed. - // This should be handled by startVncServerIfNecessary(...). + // Stop reset everything + _mode = Mode::None; + reset(); + return; } + // Unset all clients desired sources. Except the tutors desired source, this has to be the selecteds frame + for (QList::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it) + if ((*it)->client() != NULL){ + (*it)->client()->setDesiredProjectionSource(getTutorFrame()->client()->id() == (*it)->client()->id() ? getSelectedFrame()->client()->id():NO_SOURCE); + qDebug() << "ID" <<(*it)->client()->id() << "ds" << (*it)->client()->desiredProjectionSource() <<"ps"<< (*it)->client()->projectionSource(); +} + DisableButtons(); + _mode = Mode::Unicast; startVncServerIfNecessary(getSelectedFrame()->client()->id()); } } @@ -802,7 +793,8 @@ void MainWindow::onButtonStudentToTutorExclusive() // If this is the first run in this mode set the tutor as watcher for (QList::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it) if ((*it)->client() != NULL) - (*it)->client()->setWatcher(getTutorFrame()->client()->id() == (*it)->client()->id()); + // Unset all but tutors desired projection, which is student + (*it)->client()->setDesiredProjectionSource(getTutorFrame()->client()->id() == (*it)->client()->id() ? getSelectedFrame()->client()->id():NO_SOURCE); _mode = Mode::LockedUnicast; } else @@ -1062,46 +1054,34 @@ void MainWindow::onVncServerStateChange(Client* client) if (client->isActiveVncServer()) { - if (_mode == Mode::Broadcast) - { - for (QList::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it) - { - if ((*it)->client() != NULL) - { - // Unlock all online clients - (*it)->client()->lockScreen(false); - - // Start VNCclients on all online clients but source - if ((*it)->client() != client) - (*it)->client()->startVncClient(client); - } - } - } - else // !Mode::Broadcast --> Mode::LockedMC || Mode::MC +// if (_mode == Mode::Broadcast) +// { +// for (QList::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it) +// { +// if ((*it)->client() != NULL) +// { +// // Unlock all online clients +// (*it)->client()->lockScreen(false); + +// // Start VNCclients on all online clients but source +// if ((*it)->client() != client) +// (*it)->client()->startVncClient(client); +// } +// } +// } +// else { + // apply the desired projection sources for (QList::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it) { // Ignore offline clients if ( (*it)->client() != NULL) { - // if (_watchers.contains((*it)->client()->id())) - if ((*it)->client()->isWatcher()) - { - // Unlock destination and connect VNCclient - (*it)->client()->lockScreen(false); + qDebug() << "ID" <<(*it)->client()->id() << "ds" << (*it)->client()->desiredProjectionSource() <<"ps"<< (*it)->client()->projectionSource(); + if ( (*it)->client()->desiredProjectionSource() == client->id() ) (*it)->client()->startVncClient(client); - } - else if ((*it)->client()->id() == client->id() ) - { - // Unlock source - (*it)->client()->lockScreen(false); - } - else - { - // Lock others and stop their clients - (*it)->client()->lockScreen(_mode == Mode::LockedUnicast); - (*it)->client()->stopVncClient(); - } + + (*it)->client()->lockScreen((*it)->client()->desiredProjectionSource() == NO_SOURCE && _mode == Mode::LockedUnicast); } } } @@ -1109,15 +1089,16 @@ void MainWindow::onVncServerStateChange(Client* client) else { // VNC server stopped on some client or failed to start - reset local pending projection information - // foreach (Client *c, _watchers) { - // c->stopVncClient(); - // } for (QList::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it) { if ((*it)->client() != NULL) { - if ((*it)->client()->isWatcher()) + if ((*it)->client()->desiredProjectionSource() == client->id()) { + (*it)->client()->setDesiredProjectionSource(NO_SOURCE); (*it)->client()->stopVncClient(); + if (_mode == Mode::LockedUnicast) + (*it)->client()->lockScreen(true); + } } } } @@ -1135,11 +1116,10 @@ void MainWindow::onVncClientStateChange(Client* client) { // VNC Client stopped -> remove from watchers if (!client->isActiveVncClient()){ - if (getClientFromId(client->id()) != NULL) - getClientFromId(client->id())->setWatcher(false); + // client->setDesiredProjectionSource(NO_SOURCE); /* - * If noboody is watching the multicast stop VNC server + * If nobody is watching the multicast stop VNC server * If the past connection of this client is not the current * _streamingSource then the manager has to have stopped it * already. This is necessary for the race condition when a server -- cgit v1.2.3-55-g7522