Fixed GST Idle mode, added proper GST Pause mode, and finally fixed pausing with Discord RPC

This commit is contained in:
2026-03-24 13:35:17 +10:00
parent af8f359759
commit c69585b0e9
4 changed files with 92 additions and 17 deletions
+6 -7
View File
@@ -9,7 +9,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h>
#include "external/discord-rpc/include/discord_rpc.h" #include "external/discord-rpc/include/discord_rpc.h"
#include "libopensubsonic/logger.h" #include "libopensubsonic/logger.h"
#include "configHandler.h" #include "configHandler.h"
@@ -69,7 +68,6 @@ void discordrpc_update(discordrpc_data** discordrpc_struct) {
} else if ((*discordrpc_struct)->state == DISCORDRPC_STATE_PLAYING_OPENSUBSONIC || } else if ((*discordrpc_struct)->state == DISCORDRPC_STATE_PLAYING_OPENSUBSONIC ||
((*discordrpc_struct)->state == DISCORDRPC_STATE_PLAYING_LOCALFILE)) { ((*discordrpc_struct)->state == DISCORDRPC_STATE_PLAYING_LOCALFILE)) {
// Playing a song from an OpenSubsonic server // Playing a song from an OpenSubsonic server
time_t currentTime = time(NULL);
asprintf(&detailsString, "%s", (*discordrpc_struct)->songTitle); asprintf(&detailsString, "%s", (*discordrpc_struct)->songTitle);
asprintf(&stateString, "by %s", (*discordrpc_struct)->songArtist); asprintf(&stateString, "by %s", (*discordrpc_struct)->songArtist);
presence.details = detailsString; presence.details = detailsString;
@@ -78,25 +76,26 @@ void discordrpc_update(discordrpc_data** discordrpc_struct) {
// TODO As of now, local file playback does NOT deal with cover art // TODO As of now, local file playback does NOT deal with cover art
presence.largeImageKey = (*discordrpc_struct)->coverArtUrl; presence.largeImageKey = (*discordrpc_struct)->coverArtUrl;
} }
presence.startTimestamp = (long)currentTime; presence.startTimestamp = (long)((*discordrpc_struct)->startTime);
presence.endTimestamp = (long)currentTime + (*discordrpc_struct)->songLength; presence.endTimestamp = (long)((*discordrpc_struct)->startTime) + (*discordrpc_struct)->songLength;
if (configObj->discordrpc_showSysDetails) { if (configObj->discordrpc_showSysDetails) {
presence.largeImageText = discordrpc_osString; presence.largeImageText = discordrpc_osString;
} }
} else if ((*discordrpc_struct)->state == DISCORDRPC_STATE_PLAYING_INTERNETRADIO) { } else if ((*discordrpc_struct)->state == DISCORDRPC_STATE_PLAYING_INTERNETRADIO) {
// Playing an internet radio station // Playing an internet radio station
time_t currentTime = time(NULL);
asprintf(&detailsString, "%s", (*discordrpc_struct)->songTitle); asprintf(&detailsString, "%s", (*discordrpc_struct)->songTitle);
asprintf(&stateString, "Internet radio station"); asprintf(&stateString, "Internet radio station");
presence.details = detailsString; presence.details = detailsString;
presence.state = stateString; presence.state = stateString;
presence.largeImageKey = (*discordrpc_struct)->coverArtUrl; presence.largeImageKey = (*discordrpc_struct)->coverArtUrl;
presence.startTimestamp = (long)currentTime; presence.startTimestamp = (long)((*discordrpc_struct)->startTime);
if (configObj->discordrpc_showSysDetails) { if (configObj->discordrpc_showSysDetails) {
presence.largeImageText = discordrpc_osString; presence.largeImageText = discordrpc_osString;
} }
} else if ((*discordrpc_struct)->state == DISCORDRPC_STATE_PAUSED) { } else if ((*discordrpc_struct)->state == DISCORDRPC_STATE_PAUSED) {
// Player is paused
asprintf(&detailsString, "Paused");
presence.details = detailsString;
} }
presence.activity_type = DISCORD_ACTIVITY_TYPE_LISTENING; presence.activity_type = DISCORD_ACTIVITY_TYPE_LISTENING;
+2
View File
@@ -6,6 +6,7 @@
#ifndef _DISCORDRPC_H #ifndef _DISCORDRPC_H
#define _DISCORDRPC_H #define _DISCORDRPC_H
#include <time.h>
#define DISCORDRPC_STATE_IDLE 0 #define DISCORDRPC_STATE_IDLE 0
#define DISCORDRPC_STATE_PLAYING_OPENSUBSONIC 1 #define DISCORDRPC_STATE_PLAYING_OPENSUBSONIC 1
@@ -16,6 +17,7 @@
typedef struct { typedef struct {
int state; int state;
long songLength; long songLength;
time_t startTime;
char* songTitle; char* songTitle;
char* songArtist; char* songArtist;
char* coverArtUrl; char* coverArtUrl;
+76 -9
View File
@@ -11,6 +11,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <pthread.h> #include <pthread.h>
#include <unistd.h> #include <unistd.h>
#include <time.h>
#include "../configHandler.h" #include "../configHandler.h"
#include "../discordrpc.h" #include "../discordrpc.h"
#include "../libopensubsonic/logger.h" #include "../libopensubsonic/logger.h"
@@ -135,6 +136,7 @@ void* OSSPlayer_ThrdInit(void* arg) {
discordrpc_data* discordrpc = NULL; discordrpc_data* discordrpc = NULL;
discordrpc_struct_init(&discordrpc); discordrpc_struct_init(&discordrpc);
discordrpc->state = DISCORDRPC_STATE_PLAYING_INTERNETRADIO; discordrpc->state = DISCORDRPC_STATE_PLAYING_INTERNETRADIO;
discordrpc->startTime = time(NULL);
discordrpc->songTitle = strdup(songObject->title); discordrpc->songTitle = strdup(songObject->title);
discordrpc_update(&discordrpc); discordrpc_update(&discordrpc);
discordrpc_struct_deinit(&discordrpc); discordrpc_struct_deinit(&discordrpc);
@@ -149,6 +151,7 @@ void* OSSPlayer_ThrdInit(void* arg) {
discordrpc_data* discordrpc = NULL; discordrpc_data* discordrpc = NULL;
discordrpc_struct_init(&discordrpc); discordrpc_struct_init(&discordrpc);
discordrpc->state = DISCORDRPC_STATE_PLAYING_OPENSUBSONIC; discordrpc->state = DISCORDRPC_STATE_PLAYING_OPENSUBSONIC;
discordrpc->startTime = time(NULL);
discordrpc->songLength = songObject->duration; discordrpc->songLength = songObject->duration;
discordrpc->songTitle = strdup(songObject->title); discordrpc->songTitle = strdup(songObject->title);
discordrpc->songArtist = strdup(songObject->artist); discordrpc->songArtist = strdup(songObject->artist);
@@ -174,6 +177,7 @@ void* OSSPlayer_ThrdInit(void* arg) {
discordrpc_data* discordrpc = NULL; discordrpc_data* discordrpc = NULL;
discordrpc_struct_init(&discordrpc); discordrpc_struct_init(&discordrpc);
discordrpc->state = DISCORDRPC_STATE_PLAYING_LOCALFILE; discordrpc->state = DISCORDRPC_STATE_PLAYING_LOCALFILE;
discordrpc->startTime = time(NULL);
discordrpc->songLength = songObject->duration; discordrpc->songLength = songObject->duration;
discordrpc->songTitle = strdup(songObject->title); discordrpc->songTitle = strdup(songObject->title);
discordrpc->songArtist = strdup(songObject->artist); discordrpc->songArtist = strdup(songObject->artist);
@@ -190,8 +194,7 @@ void* OSSPlayer_ThrdInit(void* arg) {
} }
} }
//if (internal_OSSPQ_GetItemCount() == 0 && !isPlaying) { if (OSSPQ_getCurrentPos() == OSSPQ_getTotalPos() && isPlaying == false) {
if (OSSPQ_getCurrentPos() != OSSPQ_getTotalPos() && !isPlaying) {
// No song currently playing, and the queue is empty // No song currently playing, and the queue is empty
// Only send idle Discord RPC if needed to avoid spamming // Only send idle Discord RPC if needed to avoid spamming
@@ -422,6 +425,19 @@ void OSSPlayer_GstECont_OutVolume_set(float val) {
g_object_set(out_volume, "volume", val, NULL); g_object_set(out_volume, "volume", val, NULL);
} }
float OSSPlayer_GstECont_Playbin3_Position_Get() {
gint64 seek_pos;
if (gst_element_query_position(playbin, GST_FORMAT_TIME, &seek_pos)) {
return (float)seek_pos / GST_SECOND;
} else {
return (float)0.00;
}
}
void OSSPLayer_GstECont_Playbin3_Position_Set(float seek_pos) {
gst_element_seek_simple(playbin, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT, (gint64)(seek_pos * GST_SECOND));
}
float OSSPlayer_GstECont_Pitch_Get() { float OSSPlayer_GstECont_Pitch_Get() {
// //
} }
@@ -437,20 +453,25 @@ void OSSPlayer_GstECont_Playbin3_Stop() {
isPlaying = false; // Notify player thread to attempt to load next song isPlaying = false; // Notify player thread to attempt to load next song
} }
void OSSPlayer_GstECont_Playbin3_PlayPause() { void OSSPlayer_GstECont_Playbin3_PlayPause() {
GstState state; GstState state;
gst_element_get_state (pipeline, &state, NULL, 0); gst_element_get_state(pipeline, &state, NULL, 0);
if (state == GST_STATE_PLAYING) { if (state == GST_STATE_PLAYING) {
gst_element_set_state (pipeline, GST_STATE_PAUSED); gst_element_set_state (pipeline, GST_STATE_PAUSED);
g_print ("Paused\n");
// Issue Pause to Discord RPC
OSSPlayer_DiscordRPC_SendPaused();
} else { } else {
gst_element_set_state (pipeline, GST_STATE_PLAYING); gst_element_set_state (pipeline, GST_STATE_PLAYING);
g_print ("Playing\n");
// Get current position in song, and find start time for Discord RPC
float curr_pos = OSSPlayer_GstECont_Playbin3_Position_Get();
time_t curr_time = time(NULL);
time_t start_time = curr_time - (int)curr_pos;
// Issue Playing to Discord RPC
OSSPlayer_DiscordRPC_SendPlaying(start_time);
} }
} }
@@ -470,6 +491,14 @@ void OSSPlayer_GstECont_Playbin3_Next() {
isPlaying = false; isPlaying = false;
} }
void OSSPlayer_GstECont_Playbin3_StartQueue() {
//
}
void OSSPlayer_GstECont_Playbin3_EndQueue() {
//
}
/* /*
* Utility Functions * Utility Functions
*/ */
@@ -488,3 +517,41 @@ float OSSPlayer_CentsToPSF(float cents) {
float semitone = cents / 100.0; float semitone = cents / 100.0;
return pow(2, (semitone / 12.0f)); return pow(2, (semitone / 12.0f));
} }
/*
* Functions that utilize Discord RPC
*/
void OSSPlayer_DiscordRPC_SendPaused() {
discordrpc_data* discordrpc = NULL;
discordrpc_struct_init(&discordrpc);
discordrpc->state = DISCORDRPC_STATE_PAUSED;
discordrpc_update(&discordrpc);
discordrpc_struct_deinit(&discordrpc);
}
void OSSPlayer_DiscordRPC_SendPlaying(time_t startTime) {
OSSPQ_SongStruct* songObject = OSSPQ_getAtPos(OSSPQ_getCurrentPos());
if (songObject == NULL) {
// Severe error - There was an item in the queue, but fetching it didn't work
printf("[OSSPlayer]\n");
// TODO: this
}
if (songObject->mode == OSSPQ_MODE_OPENSUBSONIC) {
// Prepare Discord RPC
discordrpc_data* discordrpc = NULL;
discordrpc_struct_init(&discordrpc);
discordrpc->state = DISCORDRPC_STATE_PLAYING_OPENSUBSONIC;
discordrpc->startTime = startTime;
discordrpc->songLength = songObject->duration;
discordrpc->songTitle = strdup(songObject->title);
discordrpc->songArtist = strdup(songObject->artist);
if (configObj->discordrpc_showCoverArt) {
discordrpc->coverArtUrl = strdup(songObject->coverArtUrl);
}
discordrpc_update(&discordrpc);
discordrpc_struct_deinit(&discordrpc);
}
OSSPQ_FreeSongObjectC(songObject);
}
+8 -1
View File
@@ -6,6 +6,7 @@
#ifndef _PLAYER_H #ifndef _PLAYER_H
#define _PLAYER_H #define _PLAYER_H
#include <time.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@@ -24,18 +25,24 @@ float OSSPlayer_GstECont_InVolume_Get();
void OSSPlayer_GstECont_InVolume_set(float val); void OSSPlayer_GstECont_InVolume_set(float val);
float OSSPlayer_GstECont_OutVolume_Get(); float OSSPlayer_GstECont_OutVolume_Get();
void OSSPlayer_GstECont_OutVolume_set(float val); void OSSPlayer_GstECont_OutVolume_set(float val);
float OSSPlayer_GstECont_Playbin3_Position_Get();
void OSSPLayer_GstECont_Playbin3_Position_Set(float seek_pos);
float OSSPlayer_GstECont_Pitch_Get(); float OSSPlayer_GstECont_Pitch_Get();
void OSSPlayer_GstECont_Pitch_Set(float cents); void OSSPlayer_GstECont_Pitch_Set(float cents);
void OSSPlayer_GstECont_Playbin3_Stop(); void OSSPlayer_GstECont_Playbin3_Stop();
void OSSPlayer_GstECont_Playbin3_PlayPause(); void OSSPlayer_GstECont_Playbin3_PlayPause();
void OSSPlayer_GstECont_Playbin3_Prev(); void OSSPlayer_GstECont_Playbin3_Prev();
void OSSPlayer_GstECont_Playbin3_Next(); void OSSPlayer_GstECont_Playbin3_Next();
void OSSPlayer_GstECont_Playbin3_StartQueue();
void OSSPlayer_GstECont_Playbin3_EndQueue();
float OSSPlayer_DbLinMul(float db); float OSSPlayer_DbLinMul(float db);
float OSSPlayer_PitchFollow(float freq, float semitone); float OSSPlayer_PitchFollow(float freq, float semitone);
float OSSPlayer_CentsToPSF(float cents); float OSSPlayer_CentsToPSF(float cents);
void OSSPlayer_DiscordRPC_SendPaused();
void OSSPlayer_DiscordRPC_SendPlaying(time_t startTime);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif