@@ -10,11 +10,11 @@ using namespace winrt;
1010using namespace Windows ::Media::Control;
1111using namespace Windows ::Storage::Streams;
1212
13- static std::string base64Encode (const std::vector<uint8_t >& data) {
13+ static std::string base64Encode (const std::vector<uint8_t > & data) {
1414 static auto chars = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" ;
1515 std::string out;
1616 int val = 0 , valb = -6 ;
17- for (uint8_t c : data) {
17+ for (uint8_t c: data) {
1818 val = (val << 8 ) + c;
1919 valb += 8 ;
2020 while (valb >= 0 ) {
@@ -28,7 +28,7 @@ static std::string base64Encode(const std::vector<uint8_t>& data) {
2828 return out;
2929}
3030
31- static std::string getThumbnailBase64 (GlobalSystemMediaTransportControlsSessionMediaProperties const & mediaProps) {
31+ static std::string getThumbnailBase64 (GlobalSystemMediaTransportControlsSessionMediaProperties const & mediaProps) {
3232 try {
3333 const auto thumbnail = mediaProps.Thumbnail ();
3434 if (!thumbnail) return " " ;
@@ -51,13 +51,12 @@ static std::string getThumbnailBase64(GlobalSystemMediaTransportControlsSessionM
5151}
5252
5353extern " C" {
54-
5554JNIEXPORT jstring JNICALL
56- Java_dev_codeman_smtc4j_SMTC4J_getPlaybackState (JNIEnv* env, jclass) {
55+ Java_dev_codeman_smtc4j_SMTC4J_getPlaybackState (JNIEnv * env, jclass) {
5756 try {
5857 try {
5958 winrt::init_apartment ();
60- } catch (const winrt::hresult_invalid_argument&) {
59+ } catch (const winrt::hresult_invalid_argument &) {
6160 }
6261
6362 const auto manager = GlobalSystemMediaTransportControlsSessionManager::RequestAsync ().get ();
@@ -69,30 +68,34 @@ Java_dev_codeman_smtc4j_SMTC4J_getPlaybackState(JNIEnv* env, jclass) {
6968
7069 int stateCode = 0 ;
7170 switch (status) {
72- case GlobalSystemMediaTransportControlsSessionPlaybackStatus::Playing: stateCode = 2 ; break ;
73- case GlobalSystemMediaTransportControlsSessionPlaybackStatus::Paused: stateCode = 1 ; break ;
74- case GlobalSystemMediaTransportControlsSessionPlaybackStatus::Stopped: stateCode = 0 ; break ;
75- default : stateCode = -1 ; break ;
71+ case GlobalSystemMediaTransportControlsSessionPlaybackStatus::Playing: stateCode = 2 ;
72+ break ;
73+ case GlobalSystemMediaTransportControlsSessionPlaybackStatus::Paused: stateCode = 1 ;
74+ break ;
75+ case GlobalSystemMediaTransportControlsSessionPlaybackStatus::Stopped: stateCode = 0 ;
76+ break ;
77+ default : stateCode = -1 ;
78+ break ;
7679 }
7780
7881 const auto timeline = session.GetTimelineProperties ();
7982 double positionSec = timeline.Position ().count () / 10'000'000.0 ; // to seconds
8083
81- if (stateCode == 2 ) { // update position based on elapsed time while playing
84+ if (stateCode == 2 ) {
85+ // update position based on elapsed time while playing
8286 const auto lastUpdated = timeline.LastUpdatedTime ().time_since_epoch ();
8387 const auto now = winrt::clock::now ().time_since_epoch ();
8488 const auto deltaTicks = now.count () - lastUpdated.count ();
8589 positionSec += deltaTicks / 10'000'000.0 ; // to seconds
8690 }
8791
8892 const std::string json = " {"
89- " \" stateCode\" :" + std::to_string (stateCode) + " ,"
90- " \" position\" :" + std::to_string (positionSec) +
91- " }" ;
93+ " \" stateCode\" :" + std::to_string (stateCode) + " ,"
94+ " \" position\" :" + std::to_string (positionSec) +
95+ " }" ;
9296
9397 return env->NewStringUTF (json.c_str ());
94-
95- } catch (const winrt::hresult_error& e) {
98+ } catch (const winrt::hresult_error &e) {
9699 std::string err = std::string (R"( {"error":")" ) + winrt::to_string (e.message ()) + " \" }" ;
97100 return env->NewStringUTF (err.c_str ());
98101 } catch (...) {
@@ -101,11 +104,11 @@ Java_dev_codeman_smtc4j_SMTC4J_getPlaybackState(JNIEnv* env, jclass) {
101104}
102105
103106JNIEXPORT jstring JNICALL
104- Java_dev_codeman_smtc4j_SMTC4J_getMediaInfo (JNIEnv* env, jclass) {
107+ Java_dev_codeman_smtc4j_SMTC4J_getMediaInfo (JNIEnv * env, jclass) {
105108 try {
106109 try {
107110 winrt::init_apartment ();
108- } catch (const winrt::hresult_invalid_argument&) {
111+ } catch (const winrt::hresult_invalid_argument &) {
109112 }
110113
111114 const auto manager = GlobalSystemMediaTransportControlsSessionManager::RequestAsync ().get ();
@@ -120,22 +123,56 @@ Java_dev_codeman_smtc4j_SMTC4J_getMediaInfo(JNIEnv* env, jclass) {
120123 const auto sourceApp = winrt::to_string (session.SourceAppUserModelId ());
121124
122125 const std::string json = " {"
123- " \" title\" :\" " + winrt::to_string (mediaProps.Title ()) + " \" ,"
124- " \" artist\" :\" " + winrt::to_string (mediaProps.Artist ()) + " \" ,"
125- " \" album\" :\" " + winrt::to_string (mediaProps.AlbumTitle ()) + " \" ,"
126- " \" duration\" :" + std::to_string (durationSec) + " ,"
127- " \" sourceApp\" :\" " + sourceApp + " \" ,"
128- " \" thumbnailBase64\" :\" " + thumbnailBase64 + " \" "
129- " }" ;
126+ " \" title\" :\" " + winrt::to_string (mediaProps.Title ()) + " \" ,"
127+ " \" artist\" :\" " + winrt::to_string (mediaProps.Artist ()) + " \" ,"
128+ " \" album\" :\" " + winrt::to_string (mediaProps.AlbumTitle ()) + " \" ,"
129+ " \" duration\" :" + std::to_string (durationSec) + " ,"
130+ " \" sourceApp\" :\" " + sourceApp + " \" ,"
131+ " \" thumbnailBase64\" :\" " + thumbnailBase64 + " \" "
132+ " }" ;
130133
131134 return env->NewStringUTF (json.c_str ());
132-
133- } catch (const winrt::hresult_error& e) {
135+ } catch (const winrt::hresult_error &e) {
134136 const std::string err = std::string (R"( {"error":")" ) + winrt::to_string (e.message ()) + " \" }" ;
135137 return env->NewStringUTF (err.c_str ());
136138 } catch (...) {
137139 return env->NewStringUTF (R"( {"error":"unknown exception"})" );
138140 }
139141}
140142
143+ JNIEXPORT void JNICALL
144+ Java_dev_codeman_smtc4j_SMTC4J_pressMediaKey (JNIEnv *, jclass, jint keyCode) {
145+ try {
146+ try {
147+ winrt::init_apartment ();
148+ } catch (const winrt::hresult_invalid_argument &) {
149+ }
150+
151+ const auto manager = GlobalSystemMediaTransportControlsSessionManager::RequestAsync ().get ();
152+ const auto session = manager.GetCurrentSession ();
153+ if (!session) return ;
154+
155+ switch (keyCode) {
156+ case 0 : // Play
157+ session.TryPlayAsync ().get ();
158+ break ;
159+ case 1 : // Pause
160+ session.TryPauseAsync ().get ();
161+ break ;
162+ case 2 : // Stop
163+ session.TryStopAsync ().get ();
164+ break ;
165+ case 3 : // Next
166+ session.TrySkipNextAsync ().get ();
167+ break ;
168+ case 4 : // Previous
169+ session.TrySkipPreviousAsync ().get ();
170+ break ;
171+ default :
172+ break ;
173+ }
174+ } catch (...) {
175+ // Ignore exceptions for media key presses
176+ }
177+ }
141178}
0 commit comments