Updating files to 1.4.9
This commit is contained in:
parent
34e97b75aa
commit
41c7551048
@ -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
|
@ -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(¶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<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;
|
||||
}
|
@ -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
|
@ -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
2
music
@ -1 +1 @@
|
||||
Subproject commit 1db3d93e650d5b90766ad89595d8d828b8b252e1
|
||||
Subproject commit 667391a724cfd86bdc8337b098587296cac9f200
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include "../InstanceHandler.h"
|
||||
#include "ConnectedClient.h"
|
||||
|
||||
#include <event.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace std::chrono;
|
||||
using namespace ts;
|
||||
|
@ -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&);
|
||||
|
@ -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)
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include "../ConnectedClient.h"
|
||||
#include "Song.h"
|
||||
#include <MusicPlayer.h>
|
||||
#include <teaspeak/MusicPlayer.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
|
@ -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;
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <MusicPlayer.h>
|
||||
#include <teaspeak/MusicPlayer.h>
|
||||
|
||||
namespace music {
|
||||
namespace provider {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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
2
shared
@ -1 +1 @@
|
||||
Subproject commit 6bcd6ab22958941088430914c4f5485ead48bd0e
|
||||
Subproject commit 51d9a002e3311a2079b25253b7946a4b03a9baf4
|
Loading…
Reference in New Issue
Block a user