void CoreAV::groupCallCallback(void* tox, uint32_t group, uint32_t peer, const int16_t* data, unsigned samples, uint8_t channels, uint32_t sample_rate, void* core) { Q_UNUSED(tox); Core* c = static_cast<Core*>(core); const ToxPk peerPk = c->getGroupPeerPk(group, peer); const Settings& s = Settings::getInstance(); // don't play the audio if it comes from a muted peer if (s.getBlackList().contains(peerPk.toString())) { return; } CoreAV* cav = c->getAv(); auto it = cav->groupCalls.find(group); if (it == cav->groupCalls.end()) { return; } ToxGroupCall& call = it->second; emit c->groupPeerAudioPlaying(group, peer); if (call.getMuteVol() || !call.isActive()) { return; } Audio& audio = Audio::getInstance(); if(!call.havePeer(peer)) { call.addPeer(peer); } audio.playAudioBuffer(call.getAlSource(peer), data, samples, channels, sample_rate); }
/** * @brief Checks if we have a friend by public key */ bool Core::hasFriendWithPublicKey(const ToxPk& publicKey) const { if (publicKey.isEmpty()) { return false; } // TODO: error handling uint32_t friendId = tox_friend_by_public_key(tox, publicKey.getBytes(), nullptr); return friendId != std::numeric_limits<uint32_t>::max(); }
/** * @brief Fetches chat messages counts for each day from the database. * @param friendPk Friend public key to fetch. * @param from Start of period to fetch. * @param to End of period to fetch. * @return List of structs containing days offset and message count for that day. */ QList<History::DateMessages> History::getChatHistoryCounts(const ToxPk& friendPk, const QDate& from, const QDate& to) { if (!isValid()) { return {}; } QDateTime fromTime(from); QDateTime toTime(to); QList<DateMessages> counts; auto rowCallback = [&counts](const QVector<QVariant>& row) { DateMessages app; app.count = row[0].toUInt(); app.offsetDays = row[1].toUInt(); counts.append(app); }; QString queryText = QString("SELECT COUNT(history.id), ((timestamp / 1000 / 60 / 60 / 24) - %4 ) AS day " "FROM history " "JOIN peers chat ON chat_id = chat.id " "WHERE timestamp BETWEEN %1 AND %2 AND chat.public_key='%3'" "GROUP BY day;") .arg(fromTime.toMSecsSinceEpoch()) .arg(toTime.toMSecsSinceEpoch()) .arg(friendPk.toString()) .arg(QDateTime::fromMSecsSinceEpoch(0).daysTo(fromTime)); db->execNow({queryText, rowCallback}); return counts; }
QString Core::getPeerName(const ToxPk& id) const { QString name; uint32_t friendId = tox_friend_by_public_key(tox, id.getBytes(), nullptr); if (friendId == std::numeric_limits<uint32_t>::max()) { qWarning() << "getPeerName: No such peer"; return name; } const size_t nameSize = tox_friend_get_name_size(tox, friendId, nullptr); if (nameSize == SIZE_MAX) { return name; } uint8_t* cname = new uint8_t[nameSize < TOX_MAX_NAME_LENGTH ? TOX_MAX_NAME_LENGTH : nameSize]; if (!tox_friend_get_name(tox, friendId, cname, nullptr)) { qWarning() << "getPeerName: Can't get name of friend " + QString().setNum(friendId); delete[] cname; return name; } name = ToxString(cname, nameSize).getQString(); delete[] cname; return name; }
void Core::acceptFriendRequest(const ToxPk& friendPk) { // TODO: error handling uint32_t friendId = tox_friend_add_norequest(tox, friendPk.getBytes(), nullptr); if (friendId == std::numeric_limits<uint32_t>::max()) { emit failedToAddFriend(friendPk); } else { profile.saveToxSave(); emit friendAdded(friendId, friendPk); } }
QString FriendList::decideNickname(const ToxPk& friendPk, const QString& origName) { Friend* f = FriendList::findFriend(friendPk); if (f != nullptr) { return f->getDisplayedName(); } else if (!origName.isEmpty()) { return origName; } else { return friendPk.toString(); } }
void ToxGroupCall::removePeer(ToxPk peerId) { const auto& source = peers.find(peerId); if (source == peers.cend()) { qDebug() << "Peer:" << peerId.toString() << "does not have a source, can't remove"; return; } peers.erase(source); QObject::disconnect(sinkInvalid[peerId]); sinkInvalid.erase(peerId); }
/** * @brief Connects us to the Tox network */ void Core::bootstrapDht() { const Settings& s = Settings::getInstance(); QList<DhtServer> dhtServerList = s.getDhtServerList(); int listSize = dhtServerList.size(); if (listSize == 0) { qWarning() << "no bootstrap list?!?"; return; } static int j = qrand() % listSize; int i=0; while (i < 2) // i think the more we bootstrap, the more we jitter because the more we overwrite nodes { const DhtServer& dhtServer = dhtServerList[j % listSize]; qDebug() << "Connecting to "+QString(dhtServer.address.toLatin1().data()) +':'+QString().setNum(dhtServer.port)+" ("+dhtServer.name+')'; QByteArray address = dhtServer.address.toLatin1(); // TODO: constucting the pk via ToxId is a workaround ToxPk pk = ToxId{dhtServer.userId}.getPublicKey(); const uint8_t* pkPtr = reinterpret_cast<const uint8_t*>(pk.getBytes()); if (!tox_bootstrap(tox, address.constData(), dhtServer.port, pkPtr, nullptr)) { qDebug() << "Error bootstrapping from "+dhtServer.name; } if (!tox_add_tcp_relay(tox, address.constData(), dhtServer.port, pkPtr, nullptr)) { qDebug() << "Error adding TCP relay from "+dhtServer.name; } ++j; ++i; } }
/** * @brief Deletes the address associated with your current Tox ID. * @param server Server to delete the address from. * @param id ToxId to delete. * @return Status code returned from server. */ Toxme::ExecCode Toxme::deleteAddress(QString server, ToxPk id) { const QString payload{"{\"public_key\":\""+id.toString()+"\"," "\"timestamp\":"+QString().setNum(time(0))+"}"}; server = server.trimmed(); if (!server.contains("://")) server = "https://" + server; QString pubkeyUrl = server + "/pk"; QString apiUrl = server + "/api"; QNetworkReply::NetworkError error = QNetworkReply::NoError; QByteArray response = makeJsonRequest(apiUrl, prepareEncryptedJson(pubkeyUrl, 2, payload), error); return extractError(response); }