diff options
-rw-r--r-- | src/Message.h | 3 | ||||
-rw-r--r-- | src/Mumble.proto | 8 | ||||
-rw-r--r-- | src/mumble/AudioInput.cpp | 10 | ||||
-rw-r--r-- | src/mumble/AudioOutput.cpp | 2 | ||||
-rw-r--r-- | src/mumble/ConfigDialog.cpp | 1 | ||||
-rw-r--r-- | src/mumble/Global.cpp | 2 | ||||
-rw-r--r-- | src/mumble/Global.h | 2 | ||||
-rw-r--r-- | src/mumble/GlobalShortcut.h | 1 | ||||
-rw-r--r-- | src/mumble/GlobalShortcutTarget.ui | 2 | ||||
-rw-r--r-- | src/mumble/MainWindow.cpp | 202 | ||||
-rw-r--r-- | src/mumble/MainWindow.h | 15 | ||||
-rw-r--r-- | src/mumble/Messages.cpp | 12 | ||||
-rw-r--r-- | src/mumble/Settings.cpp | 35 | ||||
-rw-r--r-- | src/mumble/Settings.h | 6 | ||||
-rw-r--r-- | src/mumble/UserModel.cpp | 14 | ||||
-rw-r--r-- | src/mumble/UserModel.h | 3 |
16 files changed, 232 insertions, 86 deletions
diff --git a/src/Message.h b/src/Message.h index d45e9b890..2f4291c34 100644 --- a/src/Message.h +++ b/src/Message.h @@ -53,7 +53,8 @@ MUMBLE_MH_MSG(CryptSetup) \ MUMBLE_MH_MSG(ContextActionAdd) \ MUMBLE_MH_MSG(ContextAction) \ - MUMBLE_MH_MSG(UserList) + MUMBLE_MH_MSG(UserList) \ + MUMBLE_MH_MSG(VoiceTarget) class MessageHandler { public: diff --git a/src/Mumble.proto b/src/Mumble.proto index ad8087790..c64417ff1 100644 --- a/src/Mumble.proto +++ b/src/Mumble.proto @@ -193,11 +193,11 @@ message UserList { message VoiceTarget { message Target { - optional uint32 player_id = 1; - optional uint32 channel = 2; + repeated uint32 session = 1; + optional uint32 channel_id = 2; optional string group = 3; - optional bool links = 4; - optional bool children = 5; + optional bool links = 4 [default = false]; + optional bool children = 5 [default = false]; } optional uint32 id = 1; repeated Target targets = 2; diff --git a/src/mumble/AudioInput.cpp b/src/mumble/AudioInput.cpp index 7f5e9ef9b..29f17cddc 100644 --- a/src/mumble/AudioInput.cpp +++ b/src/mumble/AudioInput.cpp @@ -631,9 +631,9 @@ void AudioInput::encodeAudioFrame() { else if (g.s.atTransmit == Settings::PushToTalk) iIsSpeech = g.s.uiDoublePush && ((g.uiDoublePush < g.s.uiDoublePush) || (g.tDoublePush.elapsed() < g.s.uiDoublePush)); - iIsSpeech = iIsSpeech || (g.iPushToTalk > 0) || (g.iAltSpeak > 0); + iIsSpeech = iIsSpeech || (g.iPushToTalk > 0); - if (g.s.bMute || ((g.s.lmLoopMode != Settings::Local) && p && p->bMute) || g.bPushToMute) { + if (g.s.bMute || ((g.s.lmLoopMode != Settings::Local) && p && p->bMute) || g.bPushToMute || (g.iTarget < 0)) { iIsSpeech = 0; } @@ -646,7 +646,7 @@ void AudioInput::encodeAudioFrame() { } if (p) - p->setTalking(iIsSpeech, (g.iAltSpeak > 0)); + p->setTalking(iIsSpeech, (g.iTarget != 0)); if (g.s.bPushClick && (g.s.atTransmit == Settings::PushToTalk)) { AudioOutputPtr ao = g.ao; @@ -685,11 +685,9 @@ void AudioInput::flushCheck(const QByteArray &qba) { if (! qba.isEmpty() && qlFrames.count() < g.s.iFramesPerPacket) return; - int flags = 0; + int flags = g.iTarget; if (g.s.lmLoopMode == Settings::Server) flags = 0x1f; - else if (g.iAltSpeak > 0) - flags = 1; char data[1024]; data[0] = static_cast<unsigned char>(flags); diff --git a/src/mumble/AudioOutput.cpp b/src/mumble/AudioOutput.cpp index 53c4cc01d..b7e8f8ccb 100644 --- a/src/mumble/AudioOutput.cpp +++ b/src/mumble/AudioOutput.cpp @@ -382,7 +382,7 @@ bool AudioOutputSpeech::needSamples(unsigned int snum) { } if (p) - p->setTalking(bLastAlive, ((ucFlags == 1) ? true : false)); + p->setTalking(bLastAlive, ((ucFlags != 0) ? true : false)); return bLastAlive; } diff --git a/src/mumble/ConfigDialog.cpp b/src/mumble/ConfigDialog.cpp index e6781bf44..66bbfb1c2 100644 --- a/src/mumble/ConfigDialog.cpp +++ b/src/mumble/ConfigDialog.cpp @@ -244,7 +244,6 @@ void ConfigDialog::apply() { // They might have changed their keys. g.iPushToTalk = 0; - g.iAltSpeak = 0; } void ConfigDialog::accept() { diff --git a/src/mumble/Global.cpp b/src/mumble/Global.cpp index 7a7b01585..2136b04a9 100644 --- a/src/mumble/Global.cpp +++ b/src/mumble/Global.cpp @@ -41,7 +41,7 @@ Global::Global() { uiSession = 0; uiDoublePush = 1000000; iPushToTalk = 0; - iAltSpeak = 0; + iTarget = 0; bPushToMute = false; bCenterPosition = false; bEchoTest = false; diff --git a/src/mumble/Global.h b/src/mumble/Global.h index 64382ff96..594c2cea8 100644 --- a/src/mumble/Global.h +++ b/src/mumble/Global.h @@ -69,7 +69,7 @@ public: int iPushToTalk; Timer tDoublePush; quint64 uiDoublePush; - int iAltSpeak; + int iTarget; bool bPushToMute; bool bCenterPosition; bool bEchoTest; diff --git a/src/mumble/GlobalShortcut.h b/src/mumble/GlobalShortcut.h index 8ba19a207..42c406cce 100644 --- a/src/mumble/GlobalShortcut.h +++ b/src/mumble/GlobalShortcut.h @@ -53,7 +53,6 @@ class GlobalShortcut : public QObject { QString qsToolTip; QString qsWhatsThis; QString name; - QVariant data; QVariant qvDefault; bool bExpert; int idx; diff --git a/src/mumble/GlobalShortcutTarget.ui b/src/mumble/GlobalShortcutTarget.ui index 7aaa680a0..4225e26cd 100644 --- a/src/mumble/GlobalShortcutTarget.ui +++ b/src/mumble/GlobalShortcutTarget.ui @@ -24,7 +24,7 @@ <item row="2" column="0" colspan="2"> <widget class="QStackedWidget" name="qswStack"> <property name="currentIndex"> - <number>0</number> + <number>1</number> </property> <widget class="QWidget" name="qwChannelPage"> <layout class="QVBoxLayout" name="verticalLayout_2"> diff --git a/src/mumble/MainWindow.cpp b/src/mumble/MainWindow.cpp index e3afbbf1a..b15b572b3 100644 --- a/src/mumble/MainWindow.cpp +++ b/src/mumble/MainWindow.cpp @@ -187,22 +187,6 @@ void MainWindow::createActions() { gsCenterPos=new GlobalShortcut(this, idx++, tr("Force Center Position", "Global Shortcut")); gsCenterPos->setObjectName(QLatin1String("CenterPos")); - GlobalShortcut *gs; - - gs = new GlobalShortcut(this, idx++, tr("Chan Parent", "Global Shortcut")); - gs->data = 0; - connect(gs, SIGNAL(triggered(bool, QVariant)), this, SLOT(pushLink(bool))); - - for (int i = 1; i< 10;i++) { - gs = new GlobalShortcut(this, idx++, tr("Chan Sub#%1", "Global Shortcut").arg(i)); - gs->data = i; - connect(gs, SIGNAL(triggered(bool, QVariant)), this, SLOT(pushLink(bool))); - } - - gs = new GlobalShortcut(this, idx++, tr("Chan All Subs", "Global Shortcut")); - gs->data = 10; - connect(gs, SIGNAL(triggered(bool, QVariant)), this, SLOT(pushLink(bool))); - gsPushMute=new GlobalShortcut(this, idx++, tr("Push-to-Mute", "Global Shortcut")); gsPushMute->setObjectName(QLatin1String("PushToMute")); @@ -215,9 +199,6 @@ void MainWindow::createActions() { gsToggleOverlay->qsWhatsThis = tr("This will switch the states of the in-game overlay between showing everybody, just the users who are talking, and nobody.", "Global Shortcut"); connect(gsToggleOverlay, SIGNAL(down(QVariant)), g.o, SLOT(toggleShow())); - gsAltTalk=new GlobalShortcut(this, idx++, tr("Alt Push-to-Talk", "Global Shortcut")); - gsAltTalk->setObjectName(QLatin1String("AltPushToTalk")); - gsMinimal=new GlobalShortcut(this, idx++, tr("Toggle Minimal", "Global Shortcut")); gsMinimal->setObjectName(QLatin1String("ToggleMinimal")); @@ -231,7 +212,8 @@ void MainWindow::createActions() { qstiIcon->setToolTip(tr("Mumble")); qstiIcon->setObjectName(QLatin1String("Icon")); - gs = new GlobalShortcut(this, idx++, tr("Fudge it"), false, QVariant::fromValue(ShortcutTarget())); + gsWhisper = new GlobalShortcut(this, idx++, tr("Whisper"), false, QVariant::fromValue(ShortcutTarget())); + gsWhisper->setObjectName(QLatin1String("gsWhisper")); #ifndef Q_OS_MAC qstiIcon->show(); @@ -1373,24 +1355,13 @@ void MainWindow::on_PushToMute_triggered(bool down, QVariant) { g.bPushToMute = down; } -void MainWindow::on_AltPushToTalk_triggered(bool down, QVariant) { - if (down) { - g.iAltSpeak++; - g.iPushToTalk++; - } else if (g.iPushToTalk) { - g.iAltSpeak--; - g.iPushToTalk--; - } -} - void MainWindow::on_CenterPos_triggered(bool down, QVariant) { + // TODO: Make this be a targetshortcut option g.bCenterPosition = down; if (down) { - g.iAltSpeak++; g.iPushToTalk++; } else if (g.iPushToTalk) { - g.iAltSpeak--; g.iPushToTalk--; } } @@ -1411,48 +1382,151 @@ void MainWindow::on_VolumeDown_triggered(bool down, QVariant) { } } -void MainWindow::pushLink(bool down) { - if (down) { - g.iAltSpeak++; - g.iPushToTalk++; - } else if (g.iPushToTalk) { - g.iAltSpeak--; - g.iPushToTalk--; - } +Channel *MainWindow::mapChannel(int idx) const { + if (! g.uiSession) + return NULL; - if (g.uiSession == 0) - return; + Channel *c = NULL; - GlobalShortcut *gs = qobject_cast<GlobalShortcut *>(sender()); - if (! gs) - return; - int idx = gs->data.toInt(); - Channel *home = ClientUser::get(g.uiSession)->cChannel; + if (idx < 0) { + switch (idx) { + case -1: + c = Channel::get(0); + break; + case -2: + case -3: + c = ClientUser::get(g.uiSession)->cChannel; + if (idx == -2) + c = c->cParent; + break; + default: + c = pmModel->getSubChannel(c, -4 - idx); + break; + } + } else { + c = Channel::get(idx); + } + return c; +} + +void MainWindow::updateTarget() { + if (qsCurrentTargets.isEmpty()) + g.iTarget = 0; + else { + QList<ShortcutTarget> ql; + foreach(const ShortcutTarget &st, qsCurrentTargets) { + ShortcutTarget nt; + nt.bUsers = st.bUsers; + if (st.bUsers) { + foreach(const QString &hash, st.qlUsers) { + ClientUser *p = pmModel->getUser(hash); + if (p) + nt.qlSessions.append(p->uiSession); + } + if (! nt.qlSessions.isEmpty()) + ql << nt; + } else { + Channel *c = mapChannel(st.iChannel); + if (c) { + nt.bLinks = st.bLinks; + nt.bChildren = st.bChildren; + nt.iChannel = c->iId; + nt.qsGroup = st.qsGroup; + ql << nt; + } + } + } + if (ql.isEmpty()) { + g.iTarget = -1; + } else { + ++iTargetCounter; + + int idx = qmTargets.value(ql); + if (idx == 0) { + QMap<int, int> qm; + QMap<int, int>::const_iterator i; + for(i=qmTargetUse.constBegin(); i != qmTargetUse.constEnd(); ++i) { + qm.insert(i.value(), i.key()); + } - Channel *target = NULL; - switch (idx) { - case 0: - target = home->cParent; - break; - case 10: - break; - default: - target = pmModel->getSubChannel(home, idx-1); - break; + i = qm.constBegin(); + idx = i.value(); + + + + MumbleProto::VoiceTarget mpvt; + mpvt.set_id(idx); + + foreach(const ShortcutTarget &st, ql) { + MumbleProto::VoiceTarget_Target *t = mpvt.add_targets(); + if (st.bUsers) { + foreach(unsigned int uisession, st.qlSessions) + t->add_session(uisession); + } else { + t->set_channel_id(st.iChannel); + if (st.bChildren) + t->set_children(true); + if (st.bLinks) + t->set_links(true); + if (! st.qsGroup.isEmpty()) + t->set_group(u8(st.qsGroup)); + } + } + g.sh->sendMessage(mpvt); + + qmTargets.insert(ql, idx); + + ++i; + ++i; + int oldidx = i.value(); + if (oldidx) { + QHash<QList<ShortcutTarget>, int>::iterator mi; + for(mi = qmTargets.begin(); mi != qmTargets.end(); ++mi) { + if (mi.value() == oldidx) { + qmTargets.erase(mi); + + mpvt.Clear(); + mpvt.set_id(oldidx); + g.sh->sendMessage(mpvt); + + break; + } + } + } + } + qmTargetUse.insert(idx, iTargetCounter); + g.iTarget = idx; + } } +} +void MainWindow::on_gsWhisper_triggered(bool down, QVariant data) { + ShortcutTarget st = data.value<ShortcutTarget>(); - if (gsMetaChannel->active()) { - if (! target || ! down) - return; - // FIXME: This was shortcut to move to a channel. + if (down) { + if (gsMetaChannel->active()) { + if (! st.bUsers) { + Channel *c = mapChannel(st.iChannel); + if (c) { + MumbleProto::UserState mpus; + mpus.set_session(g.uiSession); + mpus.set_channel_id(c->iId); + g.sh->sendMessage(mpus); + } + return; + } + } - g.l->log(Log::Information, tr("Joining %1.").arg(target->qsName)); - } else { + qsCurrentTargets.insert(st); + updateTarget(); - // FIXME: This was shortcut to temp-link a channel. Replace with target. + g.iPushToTalk++; + } else if (g.iPushToTalk) { + qsCurrentTargets.remove(st); + updateTarget(); + g.iPushToTalk--; } } diff --git a/src/mumble/MainWindow.h b/src/mumble/MainWindow.h index 64a3ea917..28a58c2d4 100644 --- a/src/mumble/MainWindow.h +++ b/src/mumble/MainWindow.h @@ -43,6 +43,9 @@ class ServerHandler; class GlobalShortcut; class TextToSpeech; class UserModel; +class Channel; + +struct ShortcutTarget; #include "Message.h" #include "Usage.h" @@ -85,7 +88,7 @@ class MainWindow : public QMainWindow, public MessageHandler, public Ui::MainWin GlobalShortcut *gsPushTalk, *gsResetAudio, *gsMuteSelf, *gsDeafSelf; GlobalShortcut *gsUnlink, *gsCenterPos, *gsPushMute, *gsMetaChannel, *gsToggleOverlay; - GlobalShortcut *gsAltTalk, *gsMinimal, *gsVolumeUp, *gsVolumeDown; + GlobalShortcut *gsMinimal, *gsVolumeUp, *gsVolumeDown, *gsWhisper; DockTitleBar *dtbLogDockTitle, *dtbChatDockTitle; ACLEditor *aclEdit; @@ -107,6 +110,12 @@ class MainWindow : public QMainWindow, public MessageHandler, public Ui::MainWin QList<QAction *> qlChannelActions; QList<QAction *> qlUserActions; + QSet<ShortcutTarget> qsCurrentTargets; + QHash<QList<ShortcutTarget>, int> qmTargets; + QMap<int, int> qmTargetUse; + Channel *mapChannel(int idx) const; + int iTargetCounter; + void createActions(); void setupGui(); void customEvent(QEvent *evt); @@ -171,20 +180,20 @@ class MainWindow : public QMainWindow, public MessageHandler, public Ui::MainWin void on_qteLog_highlighted(const QUrl & link); void on_PushToTalk_triggered(bool, QVariant); void on_PushToMute_triggered(bool, QVariant); - void on_AltPushToTalk_triggered(bool, QVariant); void on_CenterPos_triggered(bool, QVariant); void on_VolumeUp_triggered(bool, QVariant); void on_VolumeDown_triggered(bool, QVariant); void on_gsMuteSelf_down(QVariant); void on_gsDeafSelf_down(QVariant); + void on_gsWhisper_triggered(bool, QVariant); void on_Reconnect_timeout(); void on_Icon_activated(QSystemTrayIcon::ActivationReason); void serverConnected(); void serverDisconnected(QString reason); - void pushLink(bool down); void viewCertificate(bool); void openUrl(const QUrl &url); void context_triggered(); + void updateTarget(); public: MainWindow(QWidget *parent); ~MainWindow(); diff --git a/src/mumble/Messages.cpp b/src/mumble/Messages.cpp index 77f53e33d..c47128e0b 100644 --- a/src/mumble/Messages.cpp +++ b/src/mumble/Messages.cpp @@ -96,6 +96,13 @@ void MainWindow::msgServerSync(const MumbleProto::ServerSync &msg) { pmModel->ensureSelfVisible(); pmModel->recheckLinks(); + qmTargetUse.clear(); + qmTargets.clear(); + for(int i=1;i<6;++i) { + qmTargetUse.insert(i, i); + } + iTargetCounter = 100; + AudioInputPtr ai = g.ai; if (ai) { int bw = ai->getMaxBandwidth(); @@ -163,7 +170,7 @@ void MainWindow::msgUserState(const MumbleProto::UserState &msg) { pmModel->setUserId(pDst, msg.user_id()); if (msg.has_hash()) { - pDst->qsHash = u8(msg.hash()); + pmModel->setHash(pDst, u8(msg.hash())); const QString &name = Database::getFriend(pDst->qsHash); if (! name.isEmpty()) pmModel->setFriendName(pDst, name); @@ -446,3 +453,6 @@ void MainWindow::msgUserList(const MumbleProto::UserList &msg) { userEdit = new UserEdit(msg, this); userEdit->show(); } + +void MainWindow::msgVoiceTarget(const MumbleProto::VoiceTarget &) { +} diff --git a/src/mumble/Settings.cpp b/src/mumble/Settings.cpp index 0cb5cbbdb..c89d1c34b 100644 --- a/src/mumble/Settings.cpp +++ b/src/mumble/Settings.cpp @@ -45,7 +45,40 @@ ShortcutTarget::ShortcutTarget() { } bool ShortcutTarget::isServerSpecific() const { - return (! bUsers && (iChannel > 0)); + return (! bUsers && (iChannel >= 0)); +} + +bool ShortcutTarget::operator ==(const ShortcutTarget &o) const { + if (bUsers != o.bUsers) + return false; + if (bUsers) + return (qlUsers == o.qlUsers) && (qlSessions == o.qlSessions); + else + return (iChannel == o.iChannel) && (bLinks == o.bLinks) && (bChildren == o.bChildren) && (qsGroup == o.qsGroup); +} + +quint32 qHash(const ShortcutTarget &t) { + quint32 h = 0; + if (t.bUsers) { + foreach(unsigned int u, t.qlSessions) + h ^= u; + } else { + h ^= t.iChannel; + if (t.bLinks) + h ^= 0x80000000; + if (t.bChildren) + h ^= 0x40000000; + h ^= qHash(t.qsGroup); + h = ~h; + } + return h; +} + +quint32 qHash(const QList<ShortcutTarget> &l) { + quint32 h = l.count(); + foreach(const ShortcutTarget &st, l) + h ^= qHash(st); + return h; } QDataStream &operator<<(QDataStream &qds, const ShortcutTarget &st) { diff --git a/src/mumble/Settings.h b/src/mumble/Settings.h index c94824f02..a3407cff2 100644 --- a/src/mumble/Settings.h +++ b/src/mumble/Settings.h @@ -51,14 +51,20 @@ struct Shortcut { struct ShortcutTarget { bool bUsers; QStringList qlUsers; + QList<unsigned int> qlSessions; int iChannel; QString qsGroup; bool bLinks; bool bChildren; ShortcutTarget(); bool isServerSpecific() const; + bool operator <(const ShortcutTarget &) const; + bool operator ==(const ShortcutTarget &) const; }; +quint32 qHash(const ShortcutTarget &); +quint32 qHash(const QList<ShortcutTarget> &); + QDataStream &operator<<(QDataStream &, const ShortcutTarget &); QDataStream &operator>>(QDataStream &, ShortcutTarget &); Q_DECLARE_METATYPE(ShortcutTarget); diff --git a/src/mumble/UserModel.cpp b/src/mumble/UserModel.cpp index c56dc2b07..c5ebe428d 100644 --- a/src/mumble/UserModel.cpp +++ b/src/mumble/UserModel.cpp @@ -695,6 +695,8 @@ void UserModel::removeUser(ClientUser *p) { p->cChannel = NULL; ClientUser::remove(p); + qmHashes.remove(p->qsHash); + delete p; delete item; @@ -762,6 +764,14 @@ void UserModel::setUserId(ClientUser *p, int id) { emit dataChanged(idx, idx); } +void UserModel::setHash(ClientUser *p, const QString &hash) { + if (! p->qsHash.isEmpty()) + qmHashes.remove(p->qsHash); + + p->qsHash = hash; + qmHashes.insert(p->qsHash, p); +} + void UserModel::setFriendName(ClientUser *p, const QString &name) { p->qsFriendName = name; QModelIndex idx_a = index(p, 0); @@ -908,6 +918,10 @@ ClientUser *UserModel::getUser(const QModelIndex &idx) const { return item->pUser; } +ClientUser *UserModel::getUser(const QString &hash) const { + return qmHashes.value(hash); +} + Channel *UserModel::getChannel(const QModelIndex &idx) const { if (! idx.isValid()) return NULL; diff --git a/src/mumble/UserModel.h b/src/mumble/UserModel.h index 1d400b034..fd0978c9e 100644 --- a/src/mumble/UserModel.h +++ b/src/mumble/UserModel.h @@ -96,6 +96,7 @@ class UserModel : public QAbstractItemModel { QIcon qiFriend; ModelItem *miRoot; QSet<Channel *> qsLinked; + QMap<QString, ClientUser *> qmHashes; QModelIndex index(ClientUser *, int column = 0) const; QModelIndex index(Channel *) const; @@ -123,6 +124,7 @@ class UserModel : public QAbstractItemModel { ClientUser *addUser(unsigned int id, const QString &name); ClientUser *getUser(const QModelIndex &idx) const; + ClientUser *getUser(const QString &hash) const; Channel *addChannel(int id, Channel *p, const QString &name); Channel *getChannel(const QModelIndex &idx) const; @@ -132,6 +134,7 @@ class UserModel : public QAbstractItemModel { void renameUser(ClientUser *p, const QString &name); void renameChannel(Channel *c, const QString &name); void setUserId(ClientUser *p, int id); + void setHash(ClientUser *p, const QString &hash); void setFriendName(ClientUser *p, const QString &name); void moveUser(ClientUser *p, Channel *c); |