diff --git a/MusicBot/CMakeLists.txt b/MusicBot/CMakeLists.txt index d3c227c..162655c 100644 --- a/MusicBot/CMakeLists.txt +++ b/MusicBot/CMakeLists.txt @@ -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 \ No newline at end of file diff --git a/MusicBot/main.cpp b/MusicBot/main.cpp index 3531c2c..8aca6cc 100644 --- a/MusicBot/main.cpp +++ b/MusicBot/main.cpp @@ -3,13 +3,8 @@ #include #include #include -#include +#include -extern "C" { - #include - #include - #include -} #include #include @@ -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(); + 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(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(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(¶ms); 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(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(system_clock::now() - last).count()) + " | " + to_string(duration_cast(player->currentIndex()).count())); - last = system_clock::now(); + log::log(log::debug, + "Time: " + to_string(duration_cast(system_clock::now() - last).count()) + " | " + + to_string(duration_cast(player->currentIndex()).count())); + last = system_clock::now(); //} //TODO! } snd_pcm_drain(pcm_handle); snd_pcm_close(pcm_handle); +#endif return 0; } \ No newline at end of file diff --git a/MusicBot/src/MusicPlayer.cpp b/MusicBot/src/MusicPlayer.cpp index 852799c..7122236 100644 --- a/MusicBot/src/MusicPlayer.cpp +++ b/MusicBot/src/MusicPlayer.cpp @@ -2,7 +2,7 @@ #include #include #include -#include "MusicPlayer.h" +#include "teaspeak/MusicPlayer.h" using namespace std; using namespace music; diff --git a/git-teaspeak b/git-teaspeak index 0c40ab6..5de2af1 160000 --- a/git-teaspeak +++ b/git-teaspeak @@ -1 +1 @@ -Subproject commit 0c40ab68b4249c426d784d556f0a2d978c9dede9 +Subproject commit 5de2af1665134bf4eb0ef3c952ddd55d3f41288d diff --git a/license/shared/LicenseRequest.cpp b/license/shared/LicenseRequest.cpp index 3b303fb..fc317ab 100644 --- a/license/shared/LicenseRequest.cpp +++ b/license/shared/LicenseRequest.cpp @@ -148,13 +148,13 @@ void LicenceRequest::beginRequest() { signal(SIGPIPE, SIG_IGN); - auto state = ::connect(this->file_descriptor, reinterpret_cast(&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(&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); diff --git a/music b/music index 1db3d93..667391a 160000 --- a/music +++ b/music @@ -1 +1 @@ -Subproject commit 1db3d93e650d5b90766ad89595d8d828b8b252e1 +Subproject commit 667391a724cfd86bdc8337b098587296cac9f200 diff --git a/server/src/DatabaseHelper.cpp b/server/src/DatabaseHelper.cpp index 1fc408d..ab35a59 100644 --- a/server/src/DatabaseHelper.cpp +++ b/server/src/DatabaseHelper.cpp @@ -159,79 +159,6 @@ void DatabaseHelper::deleteClient(const std::shared_ptr& 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& 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 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(time).count()); -} inline sql::result load_permissions_v2(const std::shared_ptr& 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 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); } } } diff --git a/server/src/client/ConnectedClient.cpp b/server/src/client/ConnectedClient.cpp index ccb5cef..46f9cae 100644 --- a/server/src/client/ConnectedClient.cpp +++ b/server/src/client/ConnectedClient.cpp @@ -15,6 +15,8 @@ #include "../InstanceHandler.h" #include "ConnectedClient.h" +#include + using namespace std; using namespace std::chrono; using namespace ts; diff --git a/server/src/client/ConnectedClient.h b/server/src/client/ConnectedClient.h index 17b1bb5..e91f310 100644 --- a/server/src/client/ConnectedClient.h +++ b/server/src/client/ConnectedClient.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include #include @@ -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&); diff --git a/server/src/client/command_handler/client.cpp b/server/src/client/command_handler/client.cpp index ced43f1..a8779ea 100644 --- a/server/src/client/command_handler/client.cpp +++ b/server/src/client/command_handler/client.cpp @@ -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) diff --git a/server/src/client/command_handler/helpers.h b/server/src/client/command_handler/helpers.h index a46b3d3..efc2ad9 100644 --- a/server/src/client/command_handler/helpers.h +++ b/server/src/client/command_handler/helpers.h @@ -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) { diff --git a/server/src/client/command_handler/misc.cpp b/server/src/client/command_handler/misc.cpp index e6d042c..3b06490 100644 --- a/server/src/client/command_handler/misc.cpp +++ b/server/src/client/command_handler/misc.cpp @@ -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 perms; + std::vector 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 diff --git a/server/src/client/command_handler/music.cpp b/server/src/client/command_handler/music.cpp index 44502cf..7742b58 100644 --- a/server/src/client/command_handler/music.cpp +++ b/server/src/client/command_handler/music.cpp @@ -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; diff --git a/server/src/client/music/MusicClient.cpp b/server/src/client/music/MusicClient.cpp index 3a8ed8f..a0c8de1 100644 --- a/server/src/client/music/MusicClient.cpp +++ b/server/src/client/music/MusicClient.cpp @@ -2,27 +2,13 @@ #include "src/client/voice/VoiceClient.h" #include #include -#include #include -#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([message] (const shared_ptr, const shared_ptr&, std::string& error) mutable -> std::shared_ptr { error = message; @@ -123,9 +109,8 @@ bool server::MusicClient::notifyClientMoved( std::shared_ptr 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; } } diff --git a/server/src/client/music/MusicClient.h b/server/src/client/music/MusicClient.h index 968aa38..9b1c4df 100644 --- a/server/src/client/music/MusicClient.h +++ b/server/src/client/music/MusicClient.h @@ -4,162 +4,153 @@ #include "../../music/MusicBotManager.h" #include "src/music/PlayablePlaylist.h" #include -#include +#include #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 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 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&,const std::string&); - virtual ~MusicClient() override; + MusicClient(const std::shared_ptr&,const std::string&); + virtual ~MusicClient() override; - void setSharedLock(const std::shared_ptr &_this){ - assert(_this.get() == this); - this->_this = _this; - } + void setSharedLock(const std::shared_ptr &_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 playlist() { return this->_playlist; } + std::shared_ptr 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 current_player(); - std::shared_ptr current_song(); + std::shared_ptr current_player(); + std::shared_ptr 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&); - void remove_subscriber(const std::shared_ptr&); - bool is_subscriber(const std::shared_ptr&); + void add_subscriber(const std::shared_ptr&); + void remove_subscriber(const std::shared_ptr&); + bool is_subscriber(const std::shared_ptr&); - protected: - public: - bool notifyClientMoved( - const std::shared_ptr &client, - const std::shared_ptr &target_channel, - ViewReasonId reason, - std::string msg, - std::shared_ptr invoker, - bool lock_channel_tree - ) override; + bool notifyClientMoved( + const std::shared_ptr &client, + const std::shared_ptr &target_channel, + ViewReasonId reason, + std::string msg, + std::shared_ptr 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&); + void schedule_music_tick(const std::unique_lock&, const std::shared_ptr&, 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::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 _current_song; + std::shared_ptr _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::chrono::system_clock::time_point>> subscribers; - protected: + void apply_volume(const std::shared_ptr<::music::SampleSegment> &); + void replay_song(const std::shared_ptr &, const std::function&)>& /* loaded callback */ = NULL); - void broadcast_text_message(const std::string &message); + void changePlayerState(ReplayState state); + void notifySongChange(const std::shared_ptr&); - 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&); - void schedule_music_tick(const std::unique_lock&, const std::shared_ptr&, 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::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 _current_song; - std::shared_ptr _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::chrono::system_clock::time_point>> subscribers; - - - void apply_volume(const std::shared_ptr<::music::SampleSegment> &); - void replay_song(const std::shared_ptr &, const std::function&)>& /* loaded callback */ = NULL); - - void changePlayerState(ReplayState state); - void notifySongChange(const std::shared_ptr&); - - 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& playlist) { - this->properties()[property::CLIENT_PLAYLIST_ID] = playlist ? playlist->playlist_id() : 0; - this->_playlist = playlist; - if(playlist) - playlist->_current_bot = std::dynamic_pointer_cast(this->ref()); - } - }; - } + inline void set_playlist(const std::shared_ptr& playlist) { + this->properties()[property::CLIENT_PLAYLIST_ID] = playlist ? playlist->playlist_id() : 0; + this->_playlist = playlist; + if(playlist) + playlist->_current_bot = std::dynamic_pointer_cast(this->ref()); + } + }; } DEFINE_TRANSFORMS(ts::server::MusicClient::ReplayState, uint8_t); DEFINE_TRANSFORMS(ts::server::MusicClient::UptimeMode::value, uint8_t); diff --git a/server/src/client/music/MusicClientPlayer.cpp b/server/src/client/music/MusicClientPlayer.cpp index 70177fb..c0257d6 100644 --- a/server/src/client/music/MusicClientPlayer.cpp +++ b/server/src/client/music/MusicClientPlayer.cpp @@ -3,11 +3,9 @@ #include "src/client/voice/VoiceClient.h" #include #include -#include #include #include #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 &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 &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 &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 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 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::CLIENT_PLAYER_VOLUME}); } @@ -315,7 +322,7 @@ void MusicClient::schedule_music_tick(const unique_lock& weak_ptr weak_self = dynamic_pointer_cast(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 self = weak_self.lock(); auto song = weak_song.lock(); @@ -347,7 +354,7 @@ void MusicClient::schedule_music_tick(const unique_lock& void MusicClient::schedule_stop_broadcast() { weak_ptr weak_self = dynamic_pointer_cast(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 */ diff --git a/server/src/client/music/MusicQueue.h b/server/src/client/music/MusicQueue.h index 1cb5646..59349f4 100644 --- a/server/src/client/music/MusicQueue.h +++ b/server/src/client/music/MusicQueue.h @@ -2,7 +2,7 @@ #include "../ConnectedClient.h" #include "Song.h" -#include +#include #include diff --git a/server/src/client/music/Song.h b/server/src/client/music/Song.h index 3c42191..ad0b1c7 100644 --- a/server/src/client/music/Song.h +++ b/server/src/client/music/Song.h @@ -5,7 +5,7 @@ #include #include -#include +#include 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 song_loaded_data() const { return this->data_loaded; } - inline std::shared_ptr ref() { return this->_self.lock(); } + [[nodiscard]] inline bool song_loaded() const { return this->data_loaded != nullptr; } + [[nodiscard]] inline std::shared_ptr song_loaded_data() const { return this->data_loaded; } + [[nodiscard]] inline std::shared_ptr ref() { return this->_self.lock(); } inline void set_song_id(SongId id) { this->data_static._song_id = id; diff --git a/server/src/client/music/internal_provider/channel_replay/ChannelProvider.h b/server/src/client/music/internal_provider/channel_replay/ChannelProvider.h index f446c13..4c5d3d7 100644 --- a/server/src/client/music/internal_provider/channel_replay/ChannelProvider.h +++ b/server/src/client/music/internal_provider/channel_replay/ChannelProvider.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include namespace music { namespace provider { diff --git a/server/src/lincense/LicenseHelper.cpp b/server/src/lincense/LicenseHelper.cpp index 1e77b00..05b85c1 100644 --- a/server/src/lincense/LicenseHelper.cpp +++ b/server/src/lincense/LicenseHelper.cpp @@ -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; diff --git a/server/src/manager/SqlDataManager.cpp b/server/src/manager/SqlDataManager.cpp index ef4bb70..51f2ab1 100644 --- a/server/src/manager/SqlDataManager.cpp +++ b/server/src/manager/SqlDataManager.cpp @@ -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; } diff --git a/server/src/music/MusicPlaylist.cpp b/server/src/music/MusicPlaylist.cpp index 705edd0..4e19f00 100644 --- a/server/src/music/MusicPlaylist.cpp +++ b/server/src/music/MusicPlaylist.cpp @@ -4,7 +4,7 @@ #include "src/VirtualServer.h" #include "src/client/ConnectedClient.h" #include -#include "MusicPlayer.h" +#include "teaspeak/MusicPlayer.h" using namespace ts; using namespace ts::music; diff --git a/server/src/music/MusicPlaylist.h b/server/src/music/MusicPlaylist.h index 61d9ae8..b861535 100644 --- a/server/src/music/MusicPlaylist.h +++ b/server/src/music/MusicPlaylist.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include "MusicBotManager.h" #include "PlaylistPermissions.h" diff --git a/server/src/weblist/WebListManager.cpp b/server/src/weblist/WebListManager.cpp index 6ba7ec7..382d18a 100644 --- a/server/src/weblist/WebListManager.cpp +++ b/server/src/weblist/WebListManager.cpp @@ -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_ptrscheduled_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_ptrentry_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(); + } } } } \ No newline at end of file diff --git a/server/src/weblist/WebListManager.h b/server/src/weblist/WebListManager.h index 30d3243..37faa99 100644 --- a/server/src/weblist/WebListManager.h +++ b/server/src/weblist/WebListManager.h @@ -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> entries; + std::mutex entry_lock{}; + std::condition_variable entry_cv{}; + std::deque> entries{}; }; } } \ No newline at end of file diff --git a/shared b/shared index 6bcd6ab..51d9a00 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit 6bcd6ab22958941088430914c4f5485ead48bd0e +Subproject commit 51d9a002e3311a2079b25253b7946a4b03a9baf4