mirror of
https://github.com/tuxbox-neutrino/libstb-hal.git
synced 2025-08-28 16:01:22 +02:00
libeplayer3-arm: insert original blank lines from exteplayer3.git, for better merge
This commit is contained in:
@@ -114,7 +114,7 @@ bool PlaybackDieNowRegisterCallback(PlaybackDieNowCallback callback)
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (playbackDieNowCallbacks[i] == NULL)
|
||||
{
|
||||
playbackDieNowCallbacks[i] = callback;
|
||||
@@ -135,6 +135,7 @@ static void SupervisorThread(Context_t *context)
|
||||
{
|
||||
hasThreadStarted = 1;
|
||||
playback_printf(10, ">\n");
|
||||
|
||||
while (context && context->playback && context->playback->isPlaying && !context->playback->abortRequested)
|
||||
{
|
||||
usleep(100000);
|
||||
@@ -158,19 +159,26 @@ static int PlaybackOpen(Context_t *context, PlayFiles_t *pFiles)
|
||||
{
|
||||
PlaybackStop(context);
|
||||
}
|
||||
|
||||
char *uri = pFiles->szFirstFile;
|
||||
|
||||
playback_printf(10, "URI=%s\n", uri);
|
||||
|
||||
if (context->playback->isPlaying)
|
||||
{
|
||||
// shouldn't happen
|
||||
playback_err("playback already running\n");
|
||||
return cERR_PLAYBACK_ERROR;
|
||||
}
|
||||
|
||||
char *extension = NULL;
|
||||
|
||||
context->playback->uri = strdup(uri);
|
||||
|
||||
context->playback->isFile = 0;
|
||||
context->playback->isHttp = 0;
|
||||
context->playback->noprobe = 0;
|
||||
|
||||
if (!strncmp("file://", uri, 7) || !strncmp("myts://", uri, 7))
|
||||
{
|
||||
context->playback->isFile = 1;
|
||||
@@ -183,6 +191,7 @@ static int PlaybackOpen(Context_t *context, PlayFiles_t *pFiles)
|
||||
{
|
||||
context->playback->noprobe = 0;
|
||||
}
|
||||
|
||||
extension = getExtension(context->playback->uri + 7);
|
||||
if (!extension)
|
||||
{
|
||||
@@ -207,6 +216,7 @@ static int PlaybackOpen(Context_t *context, PlayFiles_t *pFiles)
|
||||
free(context->playback->uri);
|
||||
context->playback->uri = tUri;
|
||||
}
|
||||
|
||||
if (strstr(uri, ":10000") || strstr(uri, ":31339/id="))
|
||||
{
|
||||
context->playback->noprobe = 1;
|
||||
@@ -217,6 +227,7 @@ static int PlaybackOpen(Context_t *context, PlayFiles_t *pFiles)
|
||||
playback_err("Unknown stream (%s)\n", uri);
|
||||
return cERR_PLAYBACK_ERROR;
|
||||
}
|
||||
|
||||
pFiles->szFirstFile = context->playback->uri;
|
||||
if ((context->container->Command(context, CONTAINER_ADD, extension) < 0) ||
|
||||
(!context->container->selectedContainer) ||
|
||||
@@ -225,20 +236,26 @@ static int PlaybackOpen(Context_t *context, PlayFiles_t *pFiles)
|
||||
playback_err("CONTAINER_ADD failed\n");
|
||||
return cERR_PLAYBACK_ERROR;
|
||||
}
|
||||
|
||||
playback_printf(10, "exiting with value 0\n");
|
||||
|
||||
return cERR_PLAYBACK_NO_ERROR;
|
||||
}
|
||||
|
||||
static int PlaybackClose(Context_t *context)
|
||||
{
|
||||
int ret = cERR_PLAYBACK_NO_ERROR;
|
||||
|
||||
playback_printf(10, "\n");
|
||||
|
||||
if (context->container->Command(context, CONTAINER_DEL, NULL) < 0)
|
||||
{
|
||||
playback_err("container delete failed\n");
|
||||
}
|
||||
|
||||
context->manager->audio->Command(context, MANAGER_DEL, NULL);
|
||||
context->manager->video->Command(context, MANAGER_DEL, NULL);
|
||||
|
||||
context->playback->isPaused = 0;
|
||||
context->playback->isPlaying = 0;
|
||||
context->playback->isForwarding = 0;
|
||||
@@ -250,8 +267,10 @@ static int PlaybackClose(Context_t *context)
|
||||
free(context->playback->uri);
|
||||
context->playback->uri = NULL;
|
||||
}
|
||||
|
||||
PlaybackDieNow(2);
|
||||
playback_printf(10, "exiting with value %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -259,13 +278,17 @@ static int PlaybackPlay(Context_t *context)
|
||||
{
|
||||
pthread_attr_t attr;
|
||||
int ret = cERR_PLAYBACK_NO_ERROR;
|
||||
|
||||
playback_printf(10, "\n");
|
||||
|
||||
if (!context->playback->isPlaying)
|
||||
{
|
||||
context->playback->AVSync = 1;
|
||||
context->output->Command(context, OUTPUT_AVSYNC, NULL);
|
||||
|
||||
context->playback->isCreationPhase = 1; // allows the created thread to go into wait mode
|
||||
ret = context->output->Command(context, OUTPUT_PLAY, NULL);
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
playback_err("OUTPUT_PLAY failed!\n");
|
||||
@@ -287,6 +310,7 @@ static int PlaybackPlay(Context_t *context)
|
||||
context->playback->BackWard = 0;
|
||||
context->playback->SlowMotion = 0;
|
||||
context->playback->Speed = 1;
|
||||
|
||||
if (hasThreadStarted == 0)
|
||||
{
|
||||
int error;
|
||||
@@ -302,13 +326,17 @@ static int PlaybackPlay(Context_t *context)
|
||||
playback_printf(10, "Created thread\n");
|
||||
}
|
||||
}
|
||||
|
||||
playback_printf(10, "clearing isCreationPhase!\n");
|
||||
|
||||
context->playback->isCreationPhase = 0; // allow thread to go into next state
|
||||
|
||||
ret = context->container->selectedContainer->Command(context, CONTAINER_PLAY, NULL);
|
||||
if (ret != 0)
|
||||
{
|
||||
playback_err("CONTAINER_PLAY failed!\n");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -316,19 +344,25 @@ static int PlaybackPlay(Context_t *context)
|
||||
playback_err("playback already running\n");
|
||||
ret = cERR_PLAYBACK_ERROR;
|
||||
}
|
||||
|
||||
playback_printf(10, "exiting with value %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int PlaybackPause(Context_t *context)
|
||||
{
|
||||
int ret = cERR_PLAYBACK_NO_ERROR;
|
||||
|
||||
playback_printf(10, "\n");
|
||||
|
||||
if (context->playback->isPlaying && !context->playback->isPaused)
|
||||
{
|
||||
if (context->playback->SlowMotion)
|
||||
context->output->Command(context, OUTPUT_CLEAR, NULL);
|
||||
|
||||
context->output->Command(context, OUTPUT_PAUSE, NULL);
|
||||
|
||||
context->playback->isPaused = 1;
|
||||
//context->playback->isPlaying = 1;
|
||||
context->playback->isForwarding = 0;
|
||||
@@ -341,6 +375,7 @@ static int PlaybackPause(Context_t *context)
|
||||
playback_err("playback not playing or already in pause mode\n");
|
||||
ret = cERR_PLAYBACK_ERROR;
|
||||
}
|
||||
|
||||
playback_printf(10, "exiting with value %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
@@ -348,15 +383,19 @@ static int PlaybackPause(Context_t *context)
|
||||
static int32_t PlaybackContinue(Context_t *context)
|
||||
{
|
||||
int32_t ret = cERR_PLAYBACK_NO_ERROR;
|
||||
|
||||
playback_printf(10, "\n");
|
||||
|
||||
if (context->playback->isPlaying &&
|
||||
(context->playback->isPaused || context->playback->isForwarding ||
|
||||
context->playback->BackWard || context->playback->SlowMotion))
|
||||
{
|
||||
if (context->playback->SlowMotion || context->playback->isForwarding || context->playback->BackWard)
|
||||
context->output->Command(context, OUTPUT_CLEAR, NULL);
|
||||
|
||||
if (context->playback->BackWard)
|
||||
context->output->Command(context, OUTPUT_AUDIOMUTE, "0");
|
||||
|
||||
context->playback->isPaused = 0;
|
||||
//context->playback->isPlaying = 1;
|
||||
context->playback->isForwarding = 0;
|
||||
@@ -370,6 +409,7 @@ static int32_t PlaybackContinue(Context_t *context)
|
||||
playback_err("continue not possible\n");
|
||||
ret = cERR_PLAYBACK_ERROR;
|
||||
}
|
||||
|
||||
playback_printf(10, "exiting with value %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
@@ -378,34 +418,43 @@ static int32_t PlaybackStop(Context_t *context)
|
||||
{
|
||||
int32_t ret = cERR_PLAYBACK_NO_ERROR;
|
||||
int wait_time = 20;
|
||||
|
||||
playback_printf(10, "\n");
|
||||
|
||||
PlaybackDieNow(1);
|
||||
|
||||
if (context && context->playback && context->playback->isPlaying)
|
||||
{
|
||||
|
||||
context->playback->isPaused = 0;
|
||||
context->playback->isPlaying = 0;
|
||||
context->playback->isForwarding = 0;
|
||||
context->playback->BackWard = 0;
|
||||
context->playback->SlowMotion = 0;
|
||||
context->playback->Speed = 0;
|
||||
|
||||
context->output->Command(context, OUTPUT_STOP, NULL);
|
||||
context->container->selectedContainer->Command(context, CONTAINER_STOP, NULL);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
playback_err("stop not possible\n");
|
||||
ret = cERR_PLAYBACK_ERROR;
|
||||
}
|
||||
|
||||
while ((hasThreadStarted == 1) && (--wait_time) > 0)
|
||||
{
|
||||
playback_printf(10, "Waiting for supervisor thread to terminate itself, will try another %d times\n", wait_time);
|
||||
usleep(100000);
|
||||
}
|
||||
|
||||
if (wait_time == 0)
|
||||
{
|
||||
playback_err("Timeout waiting for thread!\n");
|
||||
ret = cERR_PLAYBACK_ERROR;
|
||||
}
|
||||
|
||||
playback_printf(10, "exiting with value %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
@@ -413,16 +462,22 @@ static int32_t PlaybackStop(Context_t *context)
|
||||
static int32_t PlaybackTerminate(Context_t *context)
|
||||
{
|
||||
int32_t ret = cERR_PLAYBACK_NO_ERROR;
|
||||
|
||||
int wait_time = 20;
|
||||
|
||||
playback_printf(20, "\n");
|
||||
|
||||
PlaybackDieNow(1);
|
||||
|
||||
if (context && context->playback && context->playback->isPlaying)
|
||||
{
|
||||
//First Flush and than delete container, else e2 cant read length of file anymore
|
||||
|
||||
if (context->output->Command(context, OUTPUT_FLUSH, NULL) < 0)
|
||||
{
|
||||
playback_err("failed to flush output.\n");
|
||||
}
|
||||
|
||||
context->playback->isPaused = 0;
|
||||
context->playback->isPlaying = 0;
|
||||
context->playback->isForwarding = 0;
|
||||
@@ -435,21 +490,25 @@ static int32_t PlaybackTerminate(Context_t *context)
|
||||
else
|
||||
{
|
||||
playback_err("%p %p %d\n", context, context->playback, context->playback->isPlaying);
|
||||
|
||||
/* fixme: konfetti: we should return an error here but this seems to be a condition which
|
||||
* can happen and is not a real error, which leads to a dead neutrino. should investigate
|
||||
* here later.
|
||||
*/
|
||||
}
|
||||
|
||||
while ((hasThreadStarted == 1) && (--wait_time) > 0)
|
||||
{
|
||||
playback_printf(10, "Waiting for supervisor thread to terminate itself, will try another %d times\n", wait_time);
|
||||
usleep(100000);
|
||||
}
|
||||
|
||||
if (wait_time == 0)
|
||||
{
|
||||
playback_err("Timeout waiting for thread!\n");
|
||||
ret = cERR_PLAYBACK_ERROR;
|
||||
}
|
||||
|
||||
playback_printf(20, "exiting with value %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
@@ -457,7 +516,9 @@ static int32_t PlaybackTerminate(Context_t *context)
|
||||
static int PlaybackFastForward(Context_t *context, int *speed)
|
||||
{
|
||||
int32_t ret = cERR_PLAYBACK_NO_ERROR;
|
||||
|
||||
playback_printf(10, "speed %d\n", *speed);
|
||||
|
||||
/* Audio only forwarding not supported */
|
||||
if (context->playback->isVideo && !context->playback->isHttp && !context->playback->BackWard && (!context->playback->isPaused || context->playback->isPlaying))
|
||||
{
|
||||
@@ -477,14 +538,18 @@ static int PlaybackFastForward(Context_t *context, int *speed)
|
||||
playback_err("fast forward not possible\n");
|
||||
ret = cERR_PLAYBACK_ERROR;
|
||||
}
|
||||
|
||||
playback_printf(10, "exiting with value %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int PlaybackFastBackward(Context_t *context, int *speed)
|
||||
{
|
||||
int32_t ret = cERR_PLAYBACK_NO_ERROR;
|
||||
|
||||
playback_printf(10, "speed = %d\n", *speed);
|
||||
|
||||
/* Audio only reverse play not supported */
|
||||
if (context->playback->isVideo && !context->playback->isForwarding &&
|
||||
(!context->playback->isPaused || context->playback->isPlaying))
|
||||
@@ -508,6 +573,7 @@ static int PlaybackFastBackward(Context_t *context, int *speed)
|
||||
context->output->Command(context, OUTPUT_AUDIOMUTE, "1");
|
||||
playback_printf(1, "S %d B %d\n", context->playback->Speed, context->playback->BackWard);
|
||||
}
|
||||
|
||||
context->output->Command(context, OUTPUT_CLEAR, NULL);
|
||||
}
|
||||
else
|
||||
@@ -515,15 +581,19 @@ static int PlaybackFastBackward(Context_t *context, int *speed)
|
||||
playback_err("fast backward not possible\n");
|
||||
ret = cERR_PLAYBACK_ERROR;
|
||||
}
|
||||
|
||||
context->playback->isSeeking = 0;
|
||||
playback_printf(10, "exiting with value %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32_t PlaybackSlowMotion(Context_t *context, int *speed)
|
||||
{
|
||||
int32_t ret = cERR_PLAYBACK_NO_ERROR;
|
||||
|
||||
playback_printf(10, "\n");
|
||||
|
||||
//Audio only forwarding not supported
|
||||
if (context->playback->isVideo && !context->playback->isHttp && context->playback->isPlaying)
|
||||
{
|
||||
@@ -549,14 +619,18 @@ static int32_t PlaybackSlowMotion(Context_t *context, int *speed)
|
||||
playback_err("slowmotion not possible\n");
|
||||
ret = cERR_PLAYBACK_ERROR;
|
||||
}
|
||||
|
||||
playback_printf(10, "exiting with value %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32_t PlaybackSeek(Context_t *context, int64_t *pos, uint8_t absolute)
|
||||
{
|
||||
int32_t ret = cERR_PLAYBACK_NO_ERROR;
|
||||
|
||||
playback_printf(10, "pos: %lldd\n", *pos);
|
||||
|
||||
if (context->playback->isPlaying && !context->playback->isForwarding && !context->playback->BackWard && !context->playback->SlowMotion && !context->playback->isPaused)
|
||||
{
|
||||
context->playback->isSeeking = 1;
|
||||
@@ -576,15 +650,20 @@ static int32_t PlaybackSeek(Context_t *context, int64_t *pos, uint8_t absolute)
|
||||
playback_err("not possible\n");
|
||||
ret = cERR_PLAYBACK_ERROR;
|
||||
}
|
||||
|
||||
playback_printf(10, "exiting with value %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32_t PlaybackPts(Context_t *context, int64_t *pts)
|
||||
{
|
||||
int32_t ret = cERR_PLAYBACK_NO_ERROR;
|
||||
|
||||
playback_printf(20, "\n");
|
||||
|
||||
*pts = 0;
|
||||
|
||||
if (context->playback->isPlaying)
|
||||
{
|
||||
ret = context->output->Command(context, OUTPUT_PTS, pts);
|
||||
@@ -594,15 +673,20 @@ static int32_t PlaybackPts(Context_t *context, int64_t *pts)
|
||||
playback_err("not possible\n");
|
||||
ret = cERR_PLAYBACK_ERROR;
|
||||
}
|
||||
|
||||
playback_printf(20, "exiting with value %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32_t PlaybackGetFrameCount(Context_t *context, uint64_t *frameCount)
|
||||
{
|
||||
int ret = cERR_PLAYBACK_NO_ERROR;
|
||||
|
||||
playback_printf(20, "\n");
|
||||
|
||||
*frameCount = 0;
|
||||
|
||||
if (context->playback->isPlaying)
|
||||
{
|
||||
ret = context->output->Command(context, OUTPUT_GET_FRAME_COUNT, frameCount);
|
||||
@@ -612,15 +696,20 @@ static int32_t PlaybackGetFrameCount(Context_t *context, uint64_t *frameCount)
|
||||
playback_err("not possible\n");
|
||||
ret = cERR_PLAYBACK_ERROR;
|
||||
}
|
||||
|
||||
playback_printf(20, "exiting with value %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32_t PlaybackLength(Context_t *context, int64_t *length)
|
||||
{
|
||||
int32_t ret = cERR_PLAYBACK_NO_ERROR;
|
||||
|
||||
playback_printf(20, "\n");
|
||||
|
||||
*length = -1;
|
||||
|
||||
if (context->playback->isPlaying)
|
||||
{
|
||||
if (context->container && context->container->selectedContainer)
|
||||
@@ -633,6 +722,7 @@ static int32_t PlaybackLength(Context_t *context, int64_t *length)
|
||||
playback_err("not possible\n");
|
||||
ret = cERR_PLAYBACK_ERROR;
|
||||
}
|
||||
|
||||
playback_printf(20, "exiting with value %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
@@ -642,7 +732,9 @@ static int32_t PlaybackSwitchAudio(Context_t *context, int32_t *track)
|
||||
int32_t ret = cERR_PLAYBACK_NO_ERROR;
|
||||
int32_t curtrackid = 0;
|
||||
int32_t nextrackid = 0;
|
||||
|
||||
playback_printf(10, "\n");
|
||||
|
||||
if (context && context->playback && context->playback->isPlaying)
|
||||
{
|
||||
if (context->manager && context->manager->audio)
|
||||
@@ -656,13 +748,16 @@ static int32_t PlaybackSwitchAudio(Context_t *context, int32_t *track)
|
||||
playback_err("switch audio not possible\n");
|
||||
ret = cERR_PLAYBACK_ERROR;
|
||||
}
|
||||
|
||||
if (nextrackid != curtrackid)
|
||||
{
|
||||
|
||||
//PlaybackPause(context);
|
||||
if (context->output && context->output->audio)
|
||||
{
|
||||
context->output->audio->Command(context, OUTPUT_SWITCH, (void *)"audio");
|
||||
}
|
||||
|
||||
if (context->container && context->container->selectedContainer)
|
||||
{
|
||||
context->container->selectedContainer->Command(context, CONTAINER_SWITCH_AUDIO, &nextrackid);
|
||||
@@ -675,6 +770,7 @@ static int32_t PlaybackSwitchAudio(Context_t *context, int32_t *track)
|
||||
playback_err("switch audio not possible\n");
|
||||
ret = cERR_PLAYBACK_ERROR;
|
||||
}
|
||||
|
||||
playback_printf(10, "exiting with value %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
@@ -684,7 +780,9 @@ static int32_t PlaybackSwitchSubtitle(Context_t *context, int32_t *track)
|
||||
int32_t ret = cERR_PLAYBACK_NO_ERROR;
|
||||
int32_t curtrackid = -1;
|
||||
int32_t nextrackid = -1;
|
||||
|
||||
playback_printf(10, "Track: %d\n", *track);
|
||||
|
||||
if (context && context->playback && context->playback->isPlaying)
|
||||
{
|
||||
if (context->manager && context->manager->subtitle)
|
||||
@@ -692,12 +790,14 @@ static int32_t PlaybackSwitchSubtitle(Context_t *context, int32_t *track)
|
||||
context->manager->subtitle->Command(context, MANAGER_GET, &curtrackid);
|
||||
context->manager->subtitle->Command(context, MANAGER_SET, track);
|
||||
context->manager->subtitle->Command(context, MANAGER_GET, &nextrackid);
|
||||
|
||||
if (curtrackid != nextrackid && nextrackid > -1)
|
||||
{
|
||||
if (context->output && context->output->subtitle)
|
||||
{
|
||||
context->output->subtitle->Command(context, OUTPUT_SWITCH, (void *)"subtitle");
|
||||
}
|
||||
|
||||
if (context->container && context->container->selectedContainer)
|
||||
{
|
||||
context->container->selectedContainer->Command(context, CONTAINER_SWITCH_SUBTITLE, &nextrackid);
|
||||
@@ -715,14 +815,18 @@ static int32_t PlaybackSwitchSubtitle(Context_t *context, int32_t *track)
|
||||
playback_err("not possible\n");
|
||||
ret = cERR_PLAYBACK_ERROR;
|
||||
}
|
||||
|
||||
playback_printf(10, "exiting with value %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32_t PlaybackInfo(Context_t *context, char **infoString)
|
||||
{
|
||||
int32_t ret = cERR_PLAYBACK_NO_ERROR;
|
||||
|
||||
playback_printf(10, "\n");
|
||||
|
||||
/* konfetti comment:
|
||||
* removed if clause here (playback running) because its
|
||||
* not necessary for all container. e.g. in case of ffmpeg
|
||||
@@ -732,7 +836,9 @@ static int32_t PlaybackInfo(Context_t *context, char **infoString)
|
||||
{
|
||||
context->container->selectedContainer->Command(context, CONTAINER_INFO, infoString);
|
||||
}
|
||||
|
||||
playback_printf(10, "exiting with value %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -742,13 +848,17 @@ static int PlaybackMetadata(Context_t *context, char ***metadata)
|
||||
|
||||
if (context->container && context->container->selectedContainer)
|
||||
context->container->selectedContainer->Command(context, CONTAINER_GET_METADATA, metadata);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32_t Command(Context_t *context, PlaybackCmd_t command, void *argument)
|
||||
{
|
||||
int32_t ret = cERR_PLAYBACK_NO_ERROR;
|
||||
|
||||
playback_printf(20, "Command %d\n", command);
|
||||
|
||||
|
||||
switch (command)
|
||||
{
|
||||
case PLAYBACK_OPEN:
|
||||
@@ -851,7 +961,9 @@ static int32_t Command(Context_t *context, PlaybackCmd_t command, void *argument
|
||||
ret = cERR_PLAYBACK_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
playback_printf(20, "exiting with value %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user