Updating files to 1.4.9

This commit is contained in:
WolverinDEV 2020-02-21 20:32:25 +01:00
parent 34e97b75aa
commit 41c7551048
26 changed files with 353 additions and 388 deletions

View File

@ -17,5 +17,6 @@ add_library(TeaMusic SHARED src/MusicPlayer.cpp)
target_link_libraries(TeaMusic PUBLIC TeaSpeak libevent::core libevent::pthreads)
#The test file
#add_executable(TeaMusicTest ${MUSIC_SOURCE_FILES} main.cpp)
#target_link_libraries(TeaMusicTest ProviderFFMpeg ProviderYT ProviderOpus TeaMusic pthread ThreadPool opus asound opusfile stdc++fs dl mpg123 avformat avcodec avutil TeaSpeak CXXTerminal event jsoncpp)
add_executable(TeaMusicTest ${MUSIC_SOURCE_FILES} main.cpp)
target_link_libraries(TeaMusicTest ProviderFFMpeg ProviderYT TeaMusic pthread asound dl stdc++fs)
#ThreadPool opus asound opusfile stdc++fs dl TeaSpeak CXXTerminal event jsoncpp

View File

@ -3,13 +3,8 @@
#include <alsa/asoundlib.h>
#include <fstream>
#include <chrono>
#include <MusicPlayer.h>
#include <teaspeak/MusicPlayer.h>
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/avutil.h>
}
#include <log/LogUtils.h>
#include <CXXTerminal/Terminal.h>
@ -18,18 +13,17 @@ using namespace std;
using namespace std::chrono;
using namespace music;
void die(const char* message)
{
void die(const char *message) {
fprintf(stderr, "%s\n", message);
exit(1);
}
int main(int, char**){
logger::config::logLevel = spdlog::level::trace;
logger::config::terminalLevel = spdlog::level::trace;
//terminal::install();
logger::setup();
int main(int, char **) {
auto config = std::make_shared<logger::LoggerConfig>();
config->logfileLevel = spdlog::level::off;
config->terminalLevel = spdlog::level::trace;
config->sync = true;
logger::setup(config);
logger::updateLogLevels();
//youtube-dl -s --dump-json https://www.youtube.com/watch?v=1ifTLj_glhc
@ -37,126 +31,77 @@ int main(int, char**){
//
//printf("Length: %d\n", codec_context->frame_size / codec_context->framerate.den / codec_context->channels); //576 | 3
/*
// To initalize libao for playback
ao_initialize();
int driver = ao_default_driver_id();
music::manager::loadProviders("../../music/bin/providers/");
// The format of the decoded PCM samples
ao_sample_format sample_format;
sample_format.bits = 16;
sample_format.channels = 2;
sample_format.rate = 44100;
sample_format.byte_format = AO_FMT_NATIVE;
sample_format.matrix = 0;
ao_device* device = ao_open_live(driver, &sample_format, NULL);
AVPacket packet;
int buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
int8_t buffer[AVCODEC_MAX_AUDIO_FRAME_SIZE];
while (1) {
buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
// Read one packet into `packet`
if (av_read_frame(container, &packet) < 0) {
break; // End of lstream. Done decoding.
}
// Decodes from `packet` into the buffer
if (avcodec_decode_audio3(codec_context, (int16_t*)buffer, &buffer_size, &packet) < 1) {
break; // Error in decoding
}
// Send the buffer contents to the audio device
ao_play(device, (char*)buffer, buffer_size);
}
av_close_input_file(container);
ao_shutdown();
fprintf(stdout, "Done playing. Exiting...");
*/
music::manager::loadProviders("providers/");
#if false
std::string file = "https://www.youtube.com/watch?v=GVC5adzPpiE"; //https://www.youtube.com/watch?v=eBlg2oX0Z0Q
auto provider = music::manager::resolveProvider("YouTube", file); //test.mp3
if(!provider) return 0;
cout << "Using provider -> " << provider->providerName << endl;
cout << "Using provider -> " << provider->providerDescription << endl;
if(true) return 0;
/*
auto fut = provider->createPlayer(file);
fut.waitAndGet(nullptr);
if(fut.failed()){
log::log(log::err, "Could not create: " + fut.errorMegssage());
} else log::log(log::info, "Got!");
//VALID
/*
auto player = provider->createPlayer("https://r5---sn-4g5edned.googlevideo.com/videoplayback?lmt=1491636391724572&key=yt6&itag=251&keepalive=yes&signature=8220B0B2D85AFE6A44CAE901A9C5A5D9A2564DA4.59183C41417E91E04552835738ED0AD1592BD05E&source=youtube&clen=4017657&sparams=clen%2Cdur%2Cei%2Cgir%2Cid%2Cinitcwndbps%2Cip%2Cipbits%2Citag%2Ckeepalive%2Clmt%2Cmime%2Cmm%2Cmn%2Cms%2Cmv%2Cpl%2Crequiressl%2Csource%2Cexpire&gir=yes&expire=1516917262&initcwndbps=856250&ei=rv1pWuvYBI-AV7SlqaAE&dur=234.061&mv=m&mt=1516895537&ms=au&requiressl=yes&ip=93.230.21.99&ipbits=0&mn=sn-4g5edned&mm=31&pl=26&mime=audio%2Fwebm&id=o-ABQnAlwQxtPQJTqHMc9SiTD-bGc1YR2yogmPcVUy1Xxp&ratebypass=yes").waitAndGet(nullptr);
/*
auto player = provider->createPlayer("https://r5---sn-4g5edned.googlevideo.com/videoplayback?mn=sn-4g5edned&mm=31&gir=yes&clen=4017657&requiressl=yes&mv=m&mt=1516820571&ms=au&ei=tdhoWtv0Fd5bY1wLY5qVA&lmt=1491636391724572&key=yt6&ip=80.133.238.232&expire=1516842261&dur=234.061&beids=%5B9466594%5D&id=o-AKeOawWpz0BT9Qxuqria6qw1_eTa3is7UXit4BLIC8re&initcwndbps=591250&source=youtube&sparams=clen%2Cdur%2Cei%2Cgir%2Cid%2Cinitcwndbps%2Cip%2Cipbits%2Citag%2Ckeepalive%2Clmt%2Cmime%2Cmm%2Cmn%2Cms%2Cmv%2Cpl%2Crequiressl%2Csource%2Cexpire&ipbits=0&signature=230305B8592A57E939FDBF2D4C19C16DC2FE0D68.AC475B47E4533071F4A6EA96960384398A15D801&pl=26&itag=251&mime=audio%2Fwebm&keepalive=yes&ratebypass=yes").waitAndGet(nullptr);
*/
auto player = provider->createPlayer(file).waitAndGet(nullptr);
if(!player){
#endif
constexpr auto url = "https://streams.ilovemusic.de/iloveradio1.mp3";
auto provider = music::manager::resolveProvider("ffmpeg", url);
if (!provider) return 0;
auto player = provider->createPlayer(url, nullptr, nullptr).waitAndGet(nullptr);
if (!player) {
cerr << "Could not load youtube video" << endl;
return -1;
}
if(!player->initialize()){
if (!player->initialize(2)) {
log::log(log::err, "Could not inizalisze ffmpeg player -> " + player->error());
return 1;
}
player->registerEventHandler("main", [player](music::MusicEvent event){ //FIXME weak ptr
player->registerEventHandler("main", [player](music::MusicEvent event) { //FIXME weak ptr
log::log(log::info, "Got event " + to_string(event));
if(event == music::EVENT_ERROR) {
if (event == music::EVENT_ERROR) {
log::log(log::err, "Recived error: " + player->error());
player->clearError();
}
});
player->play();
player->forward(chrono::minutes(0));
//player->forward(chrono::minutes(0));
cout << "Song length " << duration_cast<seconds>(player->length()).count() << " seconds" << endl;
std::this_thread::sleep_for(std::chrono::seconds{600});
unsigned int pcm, tmp, dir;
#if false
snd_pcm_t *pcm{nullptr};
int err, tmp, dir;
snd_pcm_t *pcm_handle;
snd_pcm_hw_params_t *params;
snd_pcm_uframes_t frames;
int loops;
int channels = 2;
int rate = 48000;
unsigned int rate = 48000;
int seconds = duration_cast<std::chrono::seconds>(player->length()).count() + 1;
seconds = 10000;
if (pcm = snd_pcm_open(&pcm_handle, PCM_DEVICE, SND_PCM_STREAM_PLAYBACK, 0) < 0)
printf("ERROR: Can't open \"%s\" PCM device. %s\n",
PCM_DEVICE, snd_strerror(pcm));
if (err = snd_pcm_open(&pcm_handle, PCM_DEVICE, SND_PCM_STREAM_PLAYBACK, 0); err < 0)
printf("ERROR: Can't open \"%s\" PCM device. %s\n", PCM_DEVICE, snd_strerror(err));
snd_pcm_hw_params_alloca(&params);
snd_pcm_hw_params_any(pcm_handle, params);
if (pcm = snd_pcm_hw_params_set_access(pcm_handle, params,
SND_PCM_ACCESS_RW_INTERLEAVED) < 0)
printf("ERROR: Can't set interleaved mode. %s\n", snd_strerror(pcm));
if (err = snd_pcm_hw_params_set_access(pcm_handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); err < 0)
printf("ERROR: Can't set interleaved mode. %s\n", snd_strerror(err));
if (pcm = snd_pcm_hw_params_set_format(pcm_handle, params,
SND_PCM_FORMAT_S16_LE) < 0)
printf("ERROR: Can't set format. %s\n", snd_strerror(pcm));
if (err = snd_pcm_hw_params_set_format(pcm_handle, params, SND_PCM_FORMAT_S16_LE); err < 0)
printf("ERROR: Can't set format. %s\n", snd_strerror(err));
if (pcm = snd_pcm_hw_params_set_channels(pcm_handle, params, channels) < 0)
printf("ERROR: Can't set channels number. %s\n", snd_strerror(pcm));
if (err = snd_pcm_hw_params_set_channels(pcm_handle, params, channels); err < 0)
printf("ERROR: Can't set channels number. %s\n", snd_strerror(err));
if (pcm = snd_pcm_hw_params_set_rate_near(pcm_handle, params, &rate, 0) < 0)
printf("ERROR: Can't set rate. %s\n", snd_strerror(pcm));
if (err = snd_pcm_hw_params_set_rate_near(pcm_handle, params, &rate, 0); err < 0)
printf("ERROR: Can't set rate. %s\n", snd_strerror(err));
if (pcm = snd_pcm_hw_params(pcm_handle, params) < 0)
printf("ERROR: Can't set harware parameters. %s\n", snd_strerror(pcm));
if (err = snd_pcm_hw_params(pcm_handle, params); err < 0)
printf("ERROR: Can't set harware parameters. %s\n", snd_strerror(err));
printf("PCM name: '%s'\n", snd_pcm_name(pcm_handle));
printf("PCM state: %s\n", snd_pcm_state_name(snd_pcm_state(pcm_handle)));
@ -174,9 +119,9 @@ int main(int, char**){
printf("seconds: %d\n", seconds);
snd_pcm_hw_params_get_period_size(params, &frames, 0);
snd_pcm_hw_params_get_period_size(params, &frames, nullptr);
cout << "perd size: " << frames << endl;
snd_pcm_hw_params_get_period_time(params, &tmp, NULL);
snd_pcm_hw_params_get_period_time(params, &tmp, nullptr);
player->preferredSampleCount(frames);
auto last = system_clock::now();
@ -184,27 +129,30 @@ int main(int, char**){
//cout << " dur: " << duration_cast<microseconds>(system_clock::now() - last).count() << endl;
auto next = player->popNextSegment();
if(!next) {
if (!next) {
log::log(log::info, "END!");
continue;
}
retry:
if (pcm = snd_pcm_writei(pcm_handle, next->segments, next->segmentLength) == -EPIPE) {
if (err = snd_pcm_writei(pcm_handle, next->segments, next->segmentLength); err == -EPIPE) {
printf("XRUN.\n");
snd_pcm_prepare(pcm_handle);
goto retry;
} else if (pcm < 0) {
printf("ERROR. Can't write to PCM device. %s\n", snd_strerror(pcm));
printf("ERROR. Can't write to PCM device. %s\n", snd_strerror(err));
}
//if((system_clock::now() - last) > ::seconds(1)) {
log::log(log::debug, "Time: " + to_string(duration_cast<milliseconds>(system_clock::now() - last).count()) + " | " + to_string(duration_cast<milliseconds>(player->currentIndex()).count()));
last = system_clock::now();
log::log(log::debug,
"Time: " + to_string(duration_cast<milliseconds>(system_clock::now() - last).count()) + " | " +
to_string(duration_cast<milliseconds>(player->currentIndex()).count()));
last = system_clock::now();
//}
//TODO!
}
snd_pcm_drain(pcm_handle);
snd_pcm_close(pcm_handle);
#endif
return 0;
}

View File

@ -2,7 +2,7 @@
#include <algorithm>
#include <log/LogUtils.h>
#include <experimental/filesystem>
#include "MusicPlayer.h"
#include "teaspeak/MusicPlayer.h"
using namespace std;
using namespace music;

@ -1 +1 @@
Subproject commit 0c40ab68b4249c426d784d556f0a2d978c9dede9
Subproject commit 5de2af1665134bf4eb0ef3c952ddd55d3f41288d

View File

@ -148,13 +148,13 @@ void LicenceRequest::beginRequest() {
signal(SIGPIPE, SIG_IGN);
auto state = ::connect(this->file_descriptor, reinterpret_cast<const sockaddr *>(&this->remote_address), sizeof(this->remote_address));
if(state < 0 && errno != EINPROGRESS) CERR("connect() failed (" + string(strerror(errno)) + ")");
auto connect_state = ::connect(this->file_descriptor, reinterpret_cast<const sockaddr *>(&this->remote_address), sizeof(this->remote_address));
if(connect_state < 0 && errno != EINPROGRESS) CERR("connect() failed (" + string(strerror(errno)) + ")");
if(setsockopt(this->file_descriptor, SOL_SOCKET, SO_REUSEADDR, &enabled, sizeof(enabled)) < 0) CERR("could not set reuse addr");
if(setsockopt(this->file_descriptor, IPPROTO_TCP, TCP_CORK, &disabled, sizeof(disabled)) < 0) CERR("could not set no push");
if(setsockopt(this->file_descriptor, SOL_SOCKET, SO_REUSEADDR, &enabled, sizeof(enabled)) < 0); //CERR("could not set reuse addr");
if(setsockopt(this->file_descriptor, IPPROTO_TCP, TCP_CORK, &disabled, sizeof(disabled)) < 0); // CERR("could not set no push");
if(fcntl(this->file_descriptor, F_SETFD, fcntl(this->file_descriptor, F_GETFL, 0) | FD_CLOEXEC | O_NONBLOCK) < 0) CERR("Failed to set FD_CLOEXEC and O_NONBLOCK");
if(fcntl(this->file_descriptor, F_SETFD, fcntl(this->file_descriptor, F_GETFL, 0) | FD_CLOEXEC | O_NONBLOCK) < 0); // CERR("Failed to set FD_CLOEXEC and O_NONBLOCK (" + std::to_string(errno) + ")");
this->event_base = event_base_new();
this->event_read = event_new(this->event_base, this->file_descriptor, EV_READ | EV_PERSIST, LicenceRequest::handleEventRead, this);

2
music

@ -1 +1 @@
Subproject commit 1db3d93e650d5b90766ad89595d8d828b8b252e1
Subproject commit 667391a724cfd86bdc8337b098587296cac9f200

View File

@ -159,79 +159,6 @@ void DatabaseHelper::deleteClient(const std::shared_ptr<VirtualServer>& server,
//TODO delete complains
}
struct PermissionArguments {
sql::command& command;
PermissionManager* manager;
VirtualServer* server;
inline int serverId() { return this->server ? this->server->getServerId() : 0; }
};
inline sql::result load_permissions(const std::shared_ptr<VirtualServer>& server, PermissionManager* manager, sql::command& command) {
auto start = system_clock::now();
auto data = PermissionArguments{command, manager, server.get()};
return command.query([](PermissionArguments* data, int length, char** values, char** names){
permission::PermissionType key = permission::PermissionType::undefined;
permission::PermissionValue value = 0, granted = 0;
bool negated = false, skipped = false;
std::shared_ptr<BasicChannel> channel;
int index;
try {
for(index = 0; index < length; index++) {
if(strcmp(names[index], "permId") == 0) {
key = permission::resolvePermissionData(values[index])->type;
if(key == permission::unknown){
debugMessage(data->serverId(), "[SQL] Permission entry contains invalid permission type! Type: {} Command: {}", values[index], data->command.sqlCommand());
return 0;
}
if(key == permission::undefined){
debugMessage(data->serverId(), "[SQL] Permission entry contains undefined permission type! Type: {} Command: {}", values[index], data->command.sqlCommand());
return 0;
}
} else if(strcmp(names[index], "channelId") == 0) {
auto channelId = stoull(values[index]);
if(channelId > 0) {
if(!data->server)
logError(data->serverId(), "[SQL] Cant find channel for channel bound permission (No server given)! Command: {} ChannelID: {}", data->command.sqlCommand(), values[index]);
else {
channel = data->server->getChannelTree()->findChannel(channelId);
if(!channel)
logError(data->serverId(), "[SQL] Cant find channel for channel bound permission! Command: {} ChannelID: {}", data->command.sqlCommand(), values[index]);
}
}
} else if(strcmp(names[index], "value") == 0) {
value = stoi(values[index]);
} else if(strcmp(names[index], "grant") == 0) {
granted = stoi(values[index]);
} else if(strcmp(names[index], "flag_skip") == 0)
skipped = strcmp(values[index], "1") == 0;
else if(strcmp(names[index], "flag_negate") == 0)
negated = strcmp(values[index], "1") == 0;
}
} catch(std::exception& ex) {
logError(data->serverId(), "[SQL] Cant load permissions! Failed to parse value! Command: {} Message: {} Key: {} Value: {}", data->command.sqlCommand(), ex.what(),names[index], values[index]);
return 0;
}
if(key == permission::undefined) {
debugMessage(data->serverId(), "[SQL] Permission entry misses permission type! Command: {}", data->command.sqlCommand());
return 0;
}
auto permission = data->manager->registerPermission(key, value, channel);
permission->granted = granted;
permission->value = value;
permission->dbReference = true;
permission->flag_negate = negated;
permission->flag_skip = skipped;
return 0;
}, &data);
auto end = system_clock::now();
auto time = end - start;
logTrace(server ? server->getServerId() : 0, "[SQL] load_permissions(\"{}\") took {}ms", command.sqlCommand(), duration_cast<milliseconds>(time).count());
}
inline sql::result load_permissions_v2(const std::shared_ptr<VirtualServer>& server, v2::PermissionManager* manager, sql::command& command, bool test_channel /* only used for client permissions (client channel permissions) */) {
auto start = system_clock::now();
@ -493,7 +420,10 @@ std::shared_ptr<permission::v2::PermissionManager> DatabaseHelper::loadPlaylistP
for(const auto& perm : entry->permissions) {
if(perm->type == permission::SQL_PERM_PLAYLIST && perm->id == playlist_id) {
result->load_permission(perm->permission->type, {perm->value, perm->grant}, perm->flag_skip, perm->flag_negate, perm->value != permNotGranted, perm->grant != permNotGranted);
if(perm->channelId)
result->load_permission(perm->permission->type, {perm->value, perm->grant}, perm->channelId, perm->flag_skip, perm->flag_negate, perm->value != permNotGranted, perm->grant != permNotGranted);
else
result->load_permission(perm->permission->type, {perm->value, perm->grant}, perm->flag_skip, perm->flag_negate, perm->value != permNotGranted, perm->grant != permNotGranted);
}
}
}

View File

@ -15,6 +15,8 @@
#include "../InstanceHandler.h"
#include "ConnectedClient.h"
#include <event.h>
using namespace std;
using namespace std::chrono;
using namespace ts;

View File

@ -1,6 +1,6 @@
#pragma once
#include <MusicPlayer.h>
#include <teaspeak/MusicPlayer.h>
#include <misc/net.h>
#include <cstdint>
#include <src/music/PlayablePlaylist.h>
@ -544,6 +544,7 @@ namespace ts {
command_result handleCommandPlaylistAddPerm(Command&);
command_result handleCommandPlaylistDelPerm(Command&);
command_result handleCommandPlaylistClientList(Command&);
command_result handleCommandPlaylistClientPermList(Command&);
command_result handleCommandPlaylistClientAddPerm(Command&);
command_result handleCommandPlaylistClientDelPerm(Command&);

View File

@ -1055,7 +1055,9 @@ command_result ConnectedClient::handleCommandClientDBFind(Command &cmd) {
args.cmd = Command(this->getType() == CLIENT_QUERY ? "" : "notifyclientdbfind");
args.full = cmd.hasParm("details");
args.ip = permission::v2::permission_granted(1, this->calculate_permission(permission::b_client_remoteaddress_view, 0));
auto res = sql::command(this->sql, string() + "SELECT * FROM `clients` WHERE `serverId` = :sid AND `" + (uid ? "clientUid" : "lastName") + "` LIKE '" + pattern + "' LIMIT 50", variable{":sid", this->server->getServerId()}).query(
auto res = sql::command(this->sql, "SELECT * FROM `clients` WHERE `serverId` = :sid AND `" + std::string{uid ? "clientUid" : "lastName"} + "` LIKE :pattern LIMIT 50",
variable{":sid", this->server->getServerId()},
variable{":pattern", pattern}).query(
[&](DBFindArgs *ptr, int len, char **values, char **names) {
for (int index = 0; index < len; index++)
if (strcmp(names[index], "cldbid") == 0)

View File

@ -82,6 +82,7 @@ if (permission::resolvePermissionData(permType)->type == permission::PermissionT
inline bool permission_require_granted_value(ts::permission::PermissionType type) {
using namespace ts;
/*
switch (type) {
case permission::i_permission_modify_power:
@ -123,6 +124,33 @@ inline bool permission_require_granted_value(ts::permission::PermissionType type
default:
return false;
}
*/
switch (type) {
case permission::i_icon_id:
case permission::i_max_icon_filesize:
case permission::i_client_max_avatar_filesize:
case permission::i_client_max_channels:
case permission::i_client_max_permanent_channels:
case permission::i_client_max_semi_channels:
case permission::i_client_max_temporary_channels:
case permission::i_channel_max_depth:
case permission::i_channel_min_depth:
case permission::i_client_max_channel_subscriptions:
case permission::i_client_music_create_modify_max_volume:
case permission::i_max_playlist_size:
case permission::i_max_playlists:
case permission::i_client_ban_max_bantime:
case permission::i_client_max_idletime:
case permission::i_group_sort_id:
return false;
default:
return true;
}
}
inline bool permission_is_group_property(ts::permission::PermissionType type) {

View File

@ -230,6 +230,7 @@ command_result ConnectedClient::handleCommand(Command &cmd) {
else if (command == "playlistpermlist") return this->handleCommandPlaylistPermList(cmd);
else if (command == "playlistaddperm") return this->handleCommandPlaylistAddPerm(cmd);
else if (command == "playlistdelperm") return this->handleCommandPlaylistDelPerm(cmd);
else if (command == "playlistclientlist") return this->handleCommandPlaylistClientList(cmd);
else if (command == "playlistclientpermlist") return this->handleCommandPlaylistClientPermList(cmd);
else if (command == "playlistclientaddperm") return this->handleCommandPlaylistClientAddPerm(cmd);
else if (command == "playlistclientdelperm") return this->handleCommandPlaylistClientDelPerm(cmd);
@ -1462,7 +1463,7 @@ command_result ConnectedClient::handleCommandPermFind(Command &cmd) {
uint8_t t;
};
std::deque<CommandPerm> perms;
std::vector<CommandPerm> perms;
perms.resize(entries.size());
size_t index = 0;
for(const auto& entry : entries) {
@ -1515,7 +1516,7 @@ command_result ConnectedClient::handleCommandPermFind(Command &cmd) {
return &a > &b;
});
Command result("");
Command result(this->notify_response_command("notifypermfind"));
index = 0;
// http://yat.qa/ressourcen/server-query-kommentare/#permfind

View File

@ -621,6 +621,42 @@ command_result ConnectedClient::handleCommandPlaylistDelPerm(ts::Command &cmd) {
return command_result{error::ok};
}
command_result ConnectedClient::handleCommandPlaylistClientList(ts::Command &cmd) {
CMD_REF_SERVER(ref_server);
CMD_RESET_IDLE;
CMD_CHK_AND_INC_FLOOD_POINTS(25);
auto playlist = ref_server->musicManager->find_playlist(cmd["playlist_id"]);
if(!playlist) return command_result{error::playlist_invalid_id};
{
auto value = playlist->calculate_client_specific_permissions(permission::b_virtualserver_playlist_permission_list, this->ref());
if(!permission::v2::permission_granted(1, value))
return command_result{permission::b_virtualserver_playlist_permission_list};
}
auto permissions = playlist->permission_manager()->channel_permissions();
if(permissions.empty())
return command_result{error::database_empty_result};
Command result(this->notify_response_command("notifyplaylistclientlist"));
auto permission_mapper = serverInstance->getPermissionMapper();
int index = 0;
ClientDbId last_client_id{0};
result["playlist_id"] = playlist->playlist_id();
for (const auto &[perm, client, value] : permissions) {
if(last_client_id != client)
result[index++]["cldbid"] = client;
}
if(index == 0)
return command_result{error::database_empty_result};
this->sendCommand(result);
return command_result{error::ok};
}
command_result ConnectedClient::handleCommandPlaylistClientPermList(ts::Command &cmd) {
CMD_REF_SERVER(ref_server);
CMD_RESET_IDLE;

View File

@ -2,27 +2,13 @@
#include "src/client/voice/VoiceClient.h"
#include <misc/endianness.h>
#include <log/LogUtils.h>
#include <misc/memtracker.h>
#include <ThreadPool/Timer.h>
#include "Song.h"
using namespace std;
using namespace std::chrono;
using namespace ts;
using namespace ts::server;
MusicClient::loader_t MusicClient::ytLoader() {
return providerLoader("YouTube");
}
MusicClient::loader_t MusicClient::ffmpegLoader() {
return providerLoader("FFMpeg");
}
MusicClient::loader_t MusicClient::channelLoader() {
return providerLoader("ChannelProvider");
}
MusicClient::loader_t MusicClient::failedLoader(const std::string &message) {
return make_shared<music::PlayableSong::song_loader_t>([message] (const shared_ptr<VirtualServer>, const shared_ptr<music::PlayableSong>&, std::string& error) mutable -> std::shared_ptr<music::PlayableSong::LoadedData> {
error = message;
@ -123,9 +109,8 @@ bool server::MusicClient::notifyClientMoved(
std::shared_ptr<ConnectedClient> invoker,
bool lock_channel_tree) {
if(&*client == this) {
this->properties()[property::CLIENT_LAST_CHANNEL] = target_channel ? target_channel->channelId() : 0;
}
if(&*client == this && target_channel)
this->properties()[property::CLIENT_LAST_CHANNEL] = target_channel->channelId();
return true;
}
@ -155,7 +140,7 @@ void MusicClient::initialize_bot() {
unique_lock server_channel_lock(this->server->channel_tree_lock);
this->server->client_move(this->ref(), channel, nullptr, "", ViewReasonId::VREASON_USER_ACTION, true, server_channel_lock);
}
this->player.volume_modifier = this->properties()[property::CLIENT_PLAYER_VOLUME];
this->playback.volume_modifier = this->properties()[property::CLIENT_PLAYER_VOLUME];
}
void MusicClient::broadcast_text_message(const std::string &message) {
@ -168,7 +153,7 @@ void MusicClient::apply_volume(const std::shared_ptr<::music::SampleSegment> &se
for(int channel = 0; channel < seg->channels; channel++){
int16_t lane = seg->segments[sample * seg->channels + channel];
//lane *= pow(10.f, this->_volumeModifier * .05f);
lane *= this->player.volume_modifier;
lane *= this->playback.volume_modifier;
seg->segments[sample * seg->channels + channel] = (int16_t) lane;
}
}

View File

@ -4,162 +4,153 @@
#include "../../music/MusicBotManager.h"
#include "src/music/PlayablePlaylist.h"
#include <opus/opus.h>
#include <MusicPlayer.h>
#include <teaspeak/MusicPlayer.h>
#include "MusicQueue.h"
namespace ts {
namespace server {
class MusicClient : public ConnectedClient {
friend class music::MusicBotManager;
public:
struct UptimeMode {
enum value {
TIME_SINCE_CREATED = 0,
TIME_SINCE_SERVER_START
};
namespace ts::server {
class MusicClient : public ConnectedClient {
friend class music::MusicBotManager;
public:
struct UptimeMode {
enum value {
TIME_SINCE_CREATED = 0,
TIME_SINCE_SERVER_START
};
};
struct Type {
enum value {
PERMANENT,
SEMI_PERMANENT,
TEMPORARY
};
struct Type {
enum value {
PERMANENT,
SEMI_PERMANENT,
TEMPORARY
};
};
//Helper methodes
typedef std::shared_ptr<music::PlayableSong::song_loader_t> loader_t;
static loader_t ytLoader();
static loader_t ffmpegLoader();
static loader_t channelLoader();
static loader_t failedLoader(const std::string& /* error */);
static loader_t providerLoader(const std::string& name = "", std::shared_ptr<::music::manager::PlayerProvider> = nullptr);
//Helper methodes
typedef std::shared_ptr<music::PlayableSong::song_loader_t> loader_t;
static loader_t failedLoader(const std::string& /* error */);
static loader_t providerLoader(const std::string& name = "", std::shared_ptr<::music::manager::PlayerProvider> = nullptr);
enum ReplayState {
SLEEPING = 0,
LOADING,
enum ReplayState {
SLEEPING = 0,
LOADING,
PLAYING,
PAUSED,
STOPPED
};
PLAYING,
PAUSED,
STOPPED
};
MusicClient(const std::shared_ptr<VirtualServer>&,const std::string&);
virtual ~MusicClient() override;
MusicClient(const std::shared_ptr<VirtualServer>&,const std::string&);
virtual ~MusicClient() override;
void setSharedLock(const std::shared_ptr<ConnectedClient> &_this){
assert(_this.get() == this);
this->_this = _this;
}
void setSharedLock(const std::shared_ptr<ConnectedClient> &_this){
assert(_this.get() == this);
this->_this = _this;
}
//Basic TeaSpeak stuff
void sendCommand(const ts::Command &command, bool low) override;
void sendCommand(const ts::command_builder &command, bool low) override;
//Basic TeaSpeak stuff
void sendCommand(const ts::Command &command, bool low) override;
void sendCommand(const ts::command_builder &command, bool low) override;
bool disconnect(const std::string &reason) override;
bool close_connection(const std::chrono::system_clock::time_point& = std::chrono::system_clock::time_point()) override;
void initialize_bot();
bool disconnect(const std::string &reason) override;
bool close_connection(const std::chrono::system_clock::time_point& = std::chrono::system_clock::time_point()) override;
void initialize_bot();
//Music stuff
inline Type::value get_bot_type() { return this->properties()[property::CLIENT_BOT_TYPE]; }
inline void set_bot_type(Type::value type) { this->properties()[property::CLIENT_BOT_TYPE] = type; }
//Music stuff
inline Type::value get_bot_type() { return this->properties()[property::CLIENT_BOT_TYPE]; }
inline void set_bot_type(Type::value type) { this->properties()[property::CLIENT_BOT_TYPE] = type; }
ClientDbId getOwner() { return this->properties()[property::CLIENT_OWNER]; }
ReplayState player_state() { return this->_player_state; }
ClientDbId getOwner() { return this->properties()[property::CLIENT_OWNER]; }
ReplayState player_state() { return this->_player_state; }
std::shared_ptr<music::PlayablePlaylist> playlist() { return this->_playlist; }
std::shared_ptr<music::PlayablePlaylist> playlist() { return this->_playlist; }
void player_reset(bool /* trigger change */);
void stopMusic();
void playMusic();
void player_pause();
void player_reset(bool /* trigger change */);
void stopMusic();
void playMusic();
void player_pause();
void forwardSong();
void resetSong();
void rewindSong();
void forwardSong();
void resetSong();
void rewindSong();
std::shared_ptr<music::MusicPlayer> current_player();
std::shared_ptr<ts::music::PlayableSong> current_song();
std::shared_ptr<music::MusicPlayer> current_player();
std::shared_ptr<ts::music::PlayableSong> current_song();
float volumeModifier(){ return this->player.volume_modifier; }
void volume_modifier(float vol);
float volumeModifier(){ return this->playback.volume_modifier; }
void volume_modifier(float vol);
void add_subscriber(const std::shared_ptr<ConnectedClient>&);
void remove_subscriber(const std::shared_ptr<ConnectedClient>&);
bool is_subscriber(const std::shared_ptr<ConnectedClient>&);
void add_subscriber(const std::shared_ptr<ConnectedClient>&);
void remove_subscriber(const std::shared_ptr<ConnectedClient>&);
bool is_subscriber(const std::shared_ptr<ConnectedClient>&);
protected:
public:
bool notifyClientMoved(
const std::shared_ptr<ConnectedClient> &client,
const std::shared_ptr<BasicChannel> &target_channel,
ViewReasonId reason,
std::string msg,
std::shared_ptr<ConnectedClient> invoker,
bool lock_channel_tree
) override;
bool notifyClientMoved(
const std::shared_ptr<ConnectedClient> &client,
const std::shared_ptr<BasicChannel> &target_channel,
ViewReasonId reason,
std::string msg,
std::shared_ptr<ConnectedClient> invoker,
bool lock_channel_tree
) override;
protected:
void broadcast_text_message(const std::string &message);
void tick(const std::chrono::system_clock::time_point &time) override;
std::chrono::system_clock::time_point next_music_tick;
void execute_music_tick(const std::shared_ptr<ts::music::PlayableSong>&);
void schedule_music_tick(const std::unique_lock<std::recursive_timed_mutex>&, const std::shared_ptr<ts::music::PlayableSong>&, const std::chrono::system_clock::time_point&, bool = false);
void schedule_stop_broadcast();
void broadcast_music_stop(); /* only invoke while ticking */
void musicEventHandler(const std::weak_ptr<music::PlayableSong>&,::music::MusicEvent);
ReplayState _player_state;
std::recursive_timed_mutex current_song_lock;
std::recursive_timed_mutex current_song_tick_lock;
std::atomic_uint8_t current_song_lock_fail{0};
std::shared_ptr<music::PlayableSong> _current_song;
std::shared_ptr<music::PlayablePlaylist> _playlist;
ts::music::MusicBotManager* manager = nullptr;
struct {
bool last_frame_silence = true;
uint8_t frame_header = 0;
OpusEncoder* encoder = nullptr;
uint16_t packet_id = 0;
} voice;
struct {
threads::tracking_id task = 0;
float volume_modifier = 1.f;
} playback;
std::mutex subscriber_lock;
std::deque<std::tuple<std::weak_ptr<ConnectedClient>, std::chrono::system_clock::time_point>> subscribers;
protected:
void apply_volume(const std::shared_ptr<::music::SampleSegment> &);
void replay_song(const std::shared_ptr<music::PlayableSong> &, const std::function<void(const std::shared_ptr<::music::MusicPlayer>&)>& /* loaded callback */ = NULL);
void broadcast_text_message(const std::string &message);
void changePlayerState(ReplayState state);
void notifySongChange(const std::shared_ptr<music::SongInfo>&);
void tick(const std::chrono::system_clock::time_point &time) override;
std::chrono::system_clock::time_point next_music_tick;
void handle_event_song_ended();
void handle_event_song_replay_failed();
void handle_event_song_dry(); /* repeating */
void execute_music_tick(const std::shared_ptr<ts::music::PlayableSong>&);
void schedule_music_tick(const std::unique_lock<std::recursive_timed_mutex>&, const std::shared_ptr<ts::music::PlayableSong>&, const std::chrono::system_clock::time_point&, bool = false);
void schedule_stop_broadcast();
void broadcast_music_stop(); /* only invoke while ticking */
void replay_next_song();
void musicEventHandler(const std::weak_ptr<music::PlayableSong>&,::music::MusicEvent);
ReplayState _player_state;
std::recursive_timed_mutex current_song_lock;
std::recursive_timed_mutex current_song_tick_lock;
std::atomic_uint8_t current_song_lock_fail{0};
std::shared_ptr<music::PlayableSong> _current_song;
std::shared_ptr<music::PlayablePlaylist> _playlist;
ts::music::MusicBotManager* manager = nullptr;
struct {
bool last_frame_silence = true;
uint8_t frame_header = 0;
OpusEncoder* encoder = nullptr;
uint16_t packet_id = 0;
} voice;
struct {
threads::tracking_id task = 0;
float volume_modifier = 1.f;
} player;
std::mutex subscriber_lock;
std::deque<std::tuple<std::weak_ptr<ConnectedClient>, std::chrono::system_clock::time_point>> subscribers;
void apply_volume(const std::shared_ptr<::music::SampleSegment> &);
void replay_song(const std::shared_ptr<music::PlayableSong> &, const std::function<void(const std::shared_ptr<::music::MusicPlayer>&)>& /* loaded callback */ = NULL);
void changePlayerState(ReplayState state);
void notifySongChange(const std::shared_ptr<music::SongInfo>&);
void handle_event_song_ended();
void handle_event_song_replay_failed();
void handle_event_song_dry(); /* repeating */
void replay_next_song();
inline void set_playlist(const std::shared_ptr<music::PlayablePlaylist>& playlist) {
this->properties()[property::CLIENT_PLAYLIST_ID] = playlist ? playlist->playlist_id() : 0;
this->_playlist = playlist;
if(playlist)
playlist->_current_bot = std::dynamic_pointer_cast<MusicClient>(this->ref());
}
};
}
inline void set_playlist(const std::shared_ptr<music::PlayablePlaylist>& playlist) {
this->properties()[property::CLIENT_PLAYLIST_ID] = playlist ? playlist->playlist_id() : 0;
this->_playlist = playlist;
if(playlist)
playlist->_current_bot = std::dynamic_pointer_cast<MusicClient>(this->ref());
}
};
}
DEFINE_TRANSFORMS(ts::server::MusicClient::ReplayState, uint8_t);
DEFINE_TRANSFORMS(ts::server::MusicClient::UptimeMode::value, uint8_t);

View File

@ -3,11 +3,9 @@
#include "src/client/voice/VoiceClient.h"
#include <misc/endianness.h>
#include <log/LogUtils.h>
#include <misc/memtracker.h>
#include <ThreadPool/Timer.h>
#include <StringVariable.h>
#include "../../InstanceHandler.h"
#include "Song.h"
using namespace std;
using namespace std::chrono;
@ -16,14 +14,13 @@ using namespace ts::server;
#define EVENT_HANDLER_NAME "ts_music"
extern InstanceHandler* serverInstance;
void MusicClient::player_reset(bool trigger_change) {
unique_lock song_lock(this->current_song_lock);
auto song = std::move(this->_current_song);
song_lock.unlock();
if(this->player.task > 0)
music::MusicBotManager::tick_music.cancelExecute(this->player.task);
if(this->playback.task > 0)
music::MusicBotManager::tick_music.cancelExecute(this->playback.task);
if(song) {
@ -49,9 +46,8 @@ void MusicClient::player_reset(bool trigger_change) {
do { \
this->player_reset(false); \
this->handle_event_song_replay_failed(); \
if(!this->current_song()) { \
this->_player_state = ReplayState::SLEEPING; \
} \
if(!this->current_song()) \
this->changePlayerState(ReplayState::SLEEPING);\
this->broadcast_text_message(message); \
return; \
} while(0)
@ -65,7 +61,7 @@ void MusicClient::replay_song(const shared_ptr<music::PlayableSong> &entry, cons
unique_lock song_lock(this->current_song_lock);
auto loader = entry->get_loader(this->getServer(), true);
if(!loader) REPLAY_ERROR(this, "An error occurrent while trying to replay the next song! (loader is empty)");
if(!loader) REPLAY_ERROR(this, "An error occurred while trying to replay the next song! (loader is empty)");
this->changePlayerState(ReplayState::LOADING);
this->_current_song = entry;
song_lock.unlock();
@ -85,7 +81,7 @@ void MusicClient::replay_song(const shared_ptr<music::PlayableSong> &entry, cons
if(loader->succeeded() && player) {
if(!player->initialize(2)) //TODO Channel count dynamic
REPLAY_ERROR(self, "An error occurrent while trying to replay the next song! (Failed to initialize player. (" + player->error() + "))");
REPLAY_ERROR(self, "An error occurred while trying to replay the next song! (Failed to initialize player. (" + player->error() + "))");
weak_ptr weak_song = entry;
player->registerEventHandler(EVENT_HANDLER_NAME, [weak_song, weak_self](::music::MusicEvent event) {
@ -131,7 +127,7 @@ void MusicClient::replay_song(const shared_ptr<music::PlayableSong> &entry, cons
self->playMusic();
} else {
if(loader->state() == threads::FutureState::WORKING) {
REPLAY_ERROR(self, "An error occurrent while trying to replay the next song! (Loader load timeout!)");
REPLAY_ERROR(self, "An error occurred while trying to replay the next song! (Loader load timeout!)");
} else {
REPLAY_ERROR(self, "Got an error while trying to load next song: " + loader->errorMegssage());
}
@ -284,8 +280,8 @@ void MusicClient::musicEventHandler(const std::weak_ptr<ts::music::PlayableSong>
this->changePlayerState(ReplayState::PLAYING);
} else if(event == ::music::EVENT_PAUSE || event == ::music::EVENT_STOP){
debugMessage(this->getServerId(), "[MusicBot] Got stop or pause event from player. Stopping bot!");
music::MusicBotManager::tick_music.cancelExecute(this->player.task);
this->player.task = 0;
music::MusicBotManager::tick_music.cancelExecute(this->playback.task);
this->playback.task = 0;
song_lock.unlock();
this->changePlayerState(event == ::music::EVENT_PAUSE ? ReplayState::PAUSED : ReplayState::STOPPED);
@ -298,12 +294,23 @@ void MusicClient::musicEventHandler(const std::weak_ptr<ts::music::PlayableSong>
this->handle_event_song_ended();
if(song == this->current_song())
this->player_reset(true);
} else if(event == ::music::EVENT_ABORT) {
debugMessage(this->getServerId(), "[MusicBot] Got abort event from music player. Playing next song!");
song_lock.unlock();
this->broadcast_text_message("Song replay aborted due to an unrecoverable error. Replaying next song.");
auto song = this->current_song();
this->handle_event_song_ended();
if(song == this->current_song())
this->player_reset(true);
} else if(event == ::music::EVENT_INFO_UPDATE) {
}
}
void MusicClient::volume_modifier(float vol) {
this->player.volume_modifier = vol;
this->properties()[property::CLIENT_PLAYER_VOLUME] = this->player.volume_modifier;
this->playback.volume_modifier = vol;
this->properties()[property::CLIENT_PLAYER_VOLUME] = this->playback.volume_modifier;
this->server->notifyClientPropertyUpdates(_this.lock(), std::deque<property::ClientProperties>{property::CLIENT_PLAYER_VOLUME});
}
@ -315,7 +322,7 @@ void MusicClient::schedule_music_tick(const unique_lock<recursive_timed_mutex>&
weak_ptr weak_self = dynamic_pointer_cast<MusicClient>(this->ref());
weak_ptr weak_song = song;
this->player.task = music::MusicBotManager::tick_music.executeLater([weak_self, weak_song] {
this->playback.task = music::MusicBotManager::tick_music.executeLater([weak_self, weak_song] {
shared_ptr<MusicClient> self = weak_self.lock();
auto song = weak_song.lock();
@ -347,7 +354,7 @@ void MusicClient::schedule_music_tick(const unique_lock<recursive_timed_mutex>&
void MusicClient::schedule_stop_broadcast() {
weak_ptr weak_self = dynamic_pointer_cast<MusicClient>(this->ref());
this->player.task = music::MusicBotManager::tick_music.executeLater([weak_self] {
this->playback.task = music::MusicBotManager::tick_music.executeLater([weak_self] {
auto self = weak_self.lock();
if(!self) return; /* we're outdated */

View File

@ -2,7 +2,7 @@
#include "../ConnectedClient.h"
#include "Song.h"
#include <MusicPlayer.h>
#include <teaspeak/MusicPlayer.h>
#include <utility>

View File

@ -5,7 +5,7 @@
#include <functional>
#include <Definitions.h>
#include <MusicPlayer.h>
#include <teaspeak/MusicPlayer.h>
namespace ts {
namespace server {
@ -64,13 +64,13 @@ namespace ts {
return data->player;
}
std::string getUrl() const override { return this->data_static._song_url; }
ts::ClientDbId getInvoker() const override { return this->data_static._song_invoker; }
ts::SongId getSongId() const override { return this->data_static._song_id; }
[[nodiscard]] std::string getUrl() const override { return this->data_static._song_url; }
[[nodiscard]] ts::ClientDbId getInvoker() const override { return this->data_static._song_invoker; }
[[nodiscard]] ts::SongId getSongId() const override { return this->data_static._song_id; }
inline bool song_loaded() const { return this->data_loaded != nullptr; }
inline std::shared_ptr<LoadedData> song_loaded_data() const { return this->data_loaded; }
inline std::shared_ptr<PlayableSong> ref() { return this->_self.lock(); }
[[nodiscard]] inline bool song_loaded() const { return this->data_loaded != nullptr; }
[[nodiscard]] inline std::shared_ptr<LoadedData> song_loaded_data() const { return this->data_loaded; }
[[nodiscard]] inline std::shared_ptr<PlayableSong> ref() { return this->_self.lock(); }
inline void set_song_id(SongId id) {
this->data_static._song_id = id;

View File

@ -1,7 +1,7 @@
#pragma once
#include <memory>
#include <MusicPlayer.h>
#include <teaspeak/MusicPlayer.h>
namespace music {
namespace provider {

View File

@ -99,12 +99,10 @@ void LicenseHelper::tick() {
}
}
void LicenseHelper::do_request(bool verbose) {
if(verbose) {
if(config::license && config::license->isPremium())
logMessage(LOG_INSTANCE, strobf("Validating license").c_str());
else
logMessage(LOG_INSTANCE, strobf("Validating instance integrity").c_str());
}
if(config::license && config::license->isPremium())
logMessage(LOG_INSTANCE, strobf("Validating license").c_str());
else
logMessage(LOG_INSTANCE, strobf("Validating instance integrity").c_str());
this->last_request = system_clock::now();
this->scheduled_request = this->last_request + minutes(10); /* some kind of timeout */
@ -146,7 +144,6 @@ void LicenseHelper::do_request(bool verbose) {
return;
}
server_addr.sin_addr.s_addr = ((in_addr*) license_host->h_addr)->s_addr;
logger::logger(0)->debug(strobf("Requesting server {}").c_str(), inet_ntoa(server_addr.sin_addr));
int first = server_addr.sin_addr.s_addr >> 24;
if(first == 0 || first == 127 || first == 255) {
if(config::license->isPremium()) {
@ -176,12 +173,11 @@ void LicenseHelper::do_request(bool verbose) {
}
void LicenseHelper::handle_request_failed(bool verbose, const std::string& error) {
if(verbose) {
if(config::license && config::license->isPremium())
logError(LOG_INSTANCE, strobf("License validation failed: {}").c_str(), error);
else
logError(LOG_INSTANCE, strobf("Instance integrity check failed: {}").c_str(), error);
}
if(config::license && config::license->isPremium())
logError(LOG_INSTANCE, strobf("License validation failed: {}").c_str(), error);
else
logError(LOG_INSTANCE, strobf("Instance integrity check failed: {}").c_str(), error);
this->request_fail_count++;
milliseconds next_request;

View File

@ -45,7 +45,7 @@ if(!result && result.msg().find(ignore) == string::npos){
#define RESIZE_COLUMN(tblName, rowName, size) up vote EXECUTE("Could not change column size", "ALTER TABLE " tblName " ALTER COLUMN " rowName " varchar(" size ")");
#define CURRENT_DATABASE_VERSION 11
#define CURRENT_PERMISSION_VERSION 1
#define CURRENT_PERMISSION_VERSION 2
#define CLIENT_UID_LENGTH "64"
#define CLIENT_NAME_LENGTH "128"
@ -529,6 +529,24 @@ bool SqlDataManager::update_permissions(std::string &error) {
return false;
}
perm_version(1);
case 1:
if(!auto_update(permission::update::SERVER_ADMIN, "i_playlist_song_move_power", {75, true}, false, false, {75, true}))
return false;
if(!auto_update(permission::update::QUERY_ADMIN, "i_playlist_song_move_power", {100, true}, false, false, {100, true}))
return false;
if(!auto_update(permission::update::SERVER_ADMIN, "i_playlist_song_needed_move_power", {0, false}, false, false, {75, true}))
return false;
if(!auto_update(permission::update::QUERY_ADMIN, "i_playlist_song_needed_move_power", {0, false}, false, false, {100, true}))
return false;
if(!auto_update(permission::update::SERVER_ADMIN, "b_channel_conversation_message_delete", {1, true}, false, false, {75, true}))
return false;
if(!auto_update(permission::update::QUERY_ADMIN, "b_channel_conversation_message_delete", {1, true}, false, false, {100, true}))
return false;
perm_version(2);
default:
break;
}

View File

@ -4,7 +4,7 @@
#include "src/VirtualServer.h"
#include "src/client/ConnectedClient.h"
#include <log/LogUtils.h>
#include "MusicPlayer.h"
#include "teaspeak/MusicPlayer.h"
using namespace ts;
using namespace ts::music;

View File

@ -4,7 +4,7 @@
#include <Properties.h>
#include <shared_mutex>
#include <atomic>
#include <MusicPlayer.h>
#include <teaspeak/MusicPlayer.h>
#include <query/command3.h>
#include "MusicBotManager.h"
#include "PlaylistPermissions.h"

View File

@ -17,16 +17,25 @@ WebListManager::WebListManager() {
this->event_base_dispatch = std::thread([&](){
system_clock::time_point start;
while(this->event_base) {
start = system_clock::now();
::event_base_dispatch(this->event_base);
if(system_clock::now() - start < seconds(1))
this_thread::sleep_for(seconds(1));
if(event_base_got_break(this->event_base)) return;
{
std::unique_lock entry_lock{this->entry_lock};
this->entry_cv.wait(entry_lock);
if(!this->event_base) return;
}
}
});
}
WebListManager::~WebListManager() {
auto base = this->event_base;
this->event_base = nullptr;
{
std::unique_lock entry_lock{this->entry_lock};
this->event_base = nullptr;
this->entry_cv.notify_all();
entry_lock.unlock();
}
event_base_loopbreak(base);
this->event_base_dispatch.join();
@ -46,6 +55,8 @@ void WebListManager::enable_report(const std::shared_ptr<ts::server::VirtualServ
entry->scheduled_request = system_clock::now();
entry->fail_count = 0;
this->entries.push_back(entry);
this->entry_cv.notify_all();
}
}
@ -65,12 +76,13 @@ void WebListManager::disable_report(const std::shared_ptr<ts::server::VirtualSer
unique_lock lock(this->entry_lock);
for(const auto& entry : this->entries) {
if(entry->server == server) {
shared_ptr copied_entry = entry; //Copy it before erasing
shared_ptr copied_entry{entry}; //Copy it before erasing
auto it = find(this->entries.begin(), this->entries.end(), copied_entry);
if(it != this->entries.end())
this->entries.erase(it);
if(copied_entry->current_request) {
this->entry_cv.notify_all();
lock.unlock();
copied_entry->current_request->abort_sync();
}
@ -130,6 +142,12 @@ void WebListManager::tick() {
auto ref_request = entry->current_request;
ref_request->report();
}
{
/* lets run the event loop */
unique_lock lock(this->entry_lock);
this->entry_cv.notify_all();
}
}
}
}

View File

@ -38,11 +38,12 @@ namespace ts {
bool enabled = false;
private:
struct event_base* event_base = nullptr;
std::thread event_base_dispatch;
struct event_base* event_base{nullptr};
std::thread event_base_dispatch{};
std::mutex entry_lock;
std::deque<std::shared_ptr<Entry>> entries;
std::mutex entry_lock{};
std::condition_variable entry_cv{};
std::deque<std::shared_ptr<Entry>> entries{};
};
}
}

2
shared

@ -1 +1 @@
Subproject commit 6bcd6ab22958941088430914c4f5485ead48bd0e
Subproject commit 51d9a002e3311a2079b25253b7946a4b03a9baf4