-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Xerus
committed
Feb 13, 2018
0 parents
commit baedea1
Showing
9 changed files
with
327 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
.gradle | ||
/build/ | ||
|
||
.idea | ||
/out/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# mpris-java | ||
Simple MPRIS 2 implementation with Kotlin for Java | ||
|
||
This is not done, but usable. No guarantees whatsoever. | ||
|
||
Look into xerus.mpris.MPRISPlayer for a test implementation. | ||
|
||
### Todo | ||
- TrackList | ||
- better Properties integration |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile | ||
|
||
plugins { | ||
application | ||
kotlin("jvm") version "1.1.51" | ||
} | ||
|
||
java.sourceSets["main"].java.srcDir("src/main") | ||
java.sourceSets["test"].java.srcDir("src/test") | ||
|
||
group = "xerus.mpris" | ||
|
||
application { | ||
mainClassName = "xerus.mpris.MPRISPlayerKt" | ||
} | ||
|
||
repositories { | ||
jcenter() | ||
} | ||
|
||
dependencies { | ||
compile("com.github.hypfvieh", "dbus-java", "2.7.4") | ||
compile(kotlin("runtime")) | ||
} | ||
|
||
tasks { | ||
withType<KotlinCompile> { | ||
kotlinOptions.jvmTarget = "1.8" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
rootProject.name = "mpris-java" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
@file: Suppress("UNUSED") | ||
package org.mpris.MediaPlayer2 | ||
|
||
import org.freedesktop.DBus | ||
import org.freedesktop.dbus.DBusInterface | ||
import org.freedesktop.dbus.DBusInterfaceName | ||
import org.freedesktop.dbus.DBusSignal | ||
import org.freedesktop.dbus.Variant | ||
|
||
interface DefaultDBus: DBus.Properties { | ||
override fun isRemote() = false | ||
@Suppress("UNCHECKED_CAST") | ||
override fun <A: Any?> Get(interface_name: String, property_name: String): A { | ||
return GetAll(interface_name)[property_name]?.value as A | ||
} | ||
override fun <A: Any?> Set(interface_name: String, property_name: String, value: A) { | ||
GetAll(interface_name).put(property_name, Variant(value)) | ||
} | ||
} | ||
|
||
@DBusInterfaceName("org.mpris.MediaPlayer2") | ||
interface MediaPlayer2: DBusInterface { | ||
fun Raise() | ||
fun Quit() | ||
} | ||
|
||
@DBusInterfaceName("org.mpris.MediaPlayer2.Player") | ||
interface Player: DBusInterface { | ||
class Seeked(path: String, val position: Long): DBusSignal(path, position) | ||
|
||
fun Next() | ||
fun Previous() | ||
fun Pause() | ||
fun PlayPause() | ||
fun Play() | ||
fun Stop() | ||
fun Seek(x: Long) | ||
fun OpenUri(uri: String) | ||
} | ||
|
||
enum class PlaybackStatus { | ||
Playing, Paused, Stopped | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
@file: Suppress("UNUSED") | ||
package org.mpris.MediaPlayer2 | ||
|
||
import org.freedesktop.dbus.DBusInterface | ||
import org.freedesktop.dbus.DBusInterfaceName | ||
import org.freedesktop.dbus.DBusSignal | ||
import org.freedesktop.dbus.Position | ||
import org.freedesktop.dbus.Struct | ||
import org.freedesktop.dbus.UInt32 | ||
|
||
@DBusInterfaceName("org.mpris.MediaPlayer2.Playlists") | ||
interface Playlists: DBusInterface { | ||
class PlaylistChanged(path: String, val playlist: Struct2): DBusSignal(path, playlist) | ||
fun ActivatePlaylist(playlist_id: DBusInterface) | ||
fun GetPlaylists(index: UInt32, max_count: UInt32, order: String, reverse_order: Boolean): List<Playlist> | ||
} | ||
|
||
class Playlist(@field:Position(0) | ||
val a: DBusInterface, | ||
@field:Position(1) | ||
val b: String, | ||
@field:Position(2) | ||
val c: String): Struct() | ||
|
||
class Struct2(@field:Position(0) | ||
val a: DBusInterface, | ||
@field:Position(1) | ||
val b: String, | ||
@field:Position(2) | ||
val c: String): Struct() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
@file: Suppress("UNUSED") | ||
package org.mpris.MediaPlayer2 | ||
|
||
import org.freedesktop.dbus.DBusInterface | ||
import org.freedesktop.dbus.DBusSignal | ||
import org.freedesktop.dbus.Variant | ||
|
||
interface TrackList: DBusInterface { | ||
|
||
class TrackListReplacedr(path: String, val Tracks: List<DBusInterface>, | ||
val CurrentTrack: DBusInterface): DBusSignal(path, Tracks, CurrentTrack) | ||
|
||
class TrackAdded(path: String, val Metadata: Map<String, Variant<*>>, | ||
val AfterTrack: DBusInterface): DBusSignal(path, Metadata, AfterTrack) | ||
|
||
class TrackRemoved(path: String, val TrackId: DBusInterface): DBusSignal(path, TrackId) | ||
|
||
class TrackMetadataChanged(path: String, val TrackId: DBusInterface, | ||
val Metadata: Map<String, Variant<*>>): DBusSignal(path, TrackId, Metadata) | ||
|
||
fun GetTracksMetadata( | ||
TrackIds: List<DBusInterface>): List<Map<String, Variant<*>>> | ||
|
||
fun AddTrack(Uri: String, AfterTrack: DBusInterface, | ||
SetAsCurrent: Boolean) | ||
|
||
fun RemoveTrack(TrackId: DBusInterface) | ||
|
||
fun GoTo(TrackId: DBusInterface) | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
package xerus.mpris | ||
|
||
import org.freedesktop.DBus.Properties.PropertiesChanged | ||
import org.freedesktop.dbus.DBusConnection | ||
import org.freedesktop.dbus.Variant | ||
import org.freedesktop.dbus.types.DBusMapType | ||
import org.mpris.MediaPlayer2.DefaultDBus | ||
import org.mpris.MediaPlayer2.MediaPlayer2 | ||
import org.mpris.MediaPlayer2.PlaybackStatus | ||
import org.mpris.MediaPlayer2.Player | ||
import java.util.Collections | ||
import java.util.HashMap | ||
|
||
val conn = DBusConnection.getConnection(DBusConnection.SESSION) | ||
|
||
fun println(obj: String) = System.out.println(obj) | ||
operator fun <K, V> HashMap<K, V>.set(k: K, value: V) = put(k, value) | ||
|
||
fun main(args: Array<String>) { | ||
println("Connecting to DBus") | ||
conn.requestBusName("org.mpris.MediaPlayer2.PlayerFX") | ||
conn.exportObject("/org/mpris/MediaPlayer2", MPRISPlayer()) | ||
} | ||
|
||
class MPRISPlayer : MediaPlayer2, Player, DefaultDBus { | ||
|
||
val properties = HashMap<String, PropertyMap>() | ||
|
||
var status = PlaybackStatus.Stopped | ||
|
||
init { | ||
println("Constructing MPRISPlayer") | ||
// MediaPlayer2 | ||
properties["org.mpris.MediaPlayer2"] = PropertyMap { | ||
put("CanSeek", true) | ||
put("CanSeek", true) | ||
put("CanQuit", true) | ||
put("CanRaise", false) | ||
put("HasTrackList", true) | ||
put("Identity", "PlayerFX") | ||
put("SupportedUriSchemes", arrayOf("file")) | ||
put("SupportedMimeTypes", arrayOf("audio/mpeg", "audio/mp4")) | ||
//properties["DesktopEntry"] | ||
} | ||
|
||
// Player | ||
properties["org.mpris.MediaPlayer2.Player"] = PropertyMap { | ||
put("PlaybackStatus", status) | ||
put("LoopStatus", "None") | ||
put("Rate", 1.0) | ||
put("Shuffle", false) | ||
put("Metadata", Variant( | ||
PropertyMap { | ||
put("mpris:trackid", "/song/1") | ||
put("mpris:length", 10_000000) | ||
put("mpris:artUrl", "file:///home/janek/Daten/Musik/Monstercat/Aero Chord - Love & Hate EP/cover.jpeg") | ||
put("xesam:artist", arrayOf("Aero Chord", "Fractal")) | ||
put("xesam:title", "Until The End (feat. Q'AILA)") | ||
}, | ||
DBusMapType(Class.forName("java.lang.String"), Class.forName("org.freedesktop.dbus.Variant")))) | ||
put("Volume", 1.0) | ||
put("Position", 0) | ||
put("MinimumRate", 1.0) | ||
put("MaximumRate", 1.0) | ||
put("CanGoNext", true) | ||
put("CanGoPrevious", true) | ||
put("CanPlay", true) | ||
put("CanPause", true) | ||
put("CanSeek", true) | ||
put("CanControl", true) | ||
} | ||
|
||
// Playlist | ||
/*properties["PlaylistCount"] = Variant() | ||
// u Read only | ||
properties["Orderings"] = Variant() | ||
// as (Playlist_Ordering_List) Read only | ||
properties["ActivePlaylist"] = Variant() | ||
// (b(oss)) (Maybe_Playlist) Read only | ||
*/ | ||
|
||
// TrackList | ||
/*properties["Tracks"] = Variant() | ||
// ao (Track_Id_List) Read only | ||
properties["CanEditTracks"] = Variant() | ||
// b Read only*/ | ||
println("MPRISPlayer constructed") | ||
} | ||
|
||
override fun GetAll(interface_name: String): Map<String, Variant<*>> = properties[interface_name]!! | ||
|
||
fun <A: Any> updateProperty(interface_name: String, name: String, value: A) { | ||
println("Updating $name of $interface_name to $value") | ||
val new = Variant(value) | ||
properties[interface_name]!![name] = new | ||
try { | ||
conn.sendSignal(PropertiesChanged("/org/mpris/MediaPlayer2", interface_name, Collections.singletonMap(name, new) as Map<String, Variant<*>>, Collections.emptyList())) | ||
} catch (e: Throwable) { | ||
e.printStackTrace() | ||
} | ||
} | ||
|
||
fun updateStatus(status: PlaybackStatus) { | ||
this.status = status | ||
updateProperty("org.mpris.MediaPlayer2.Player", "PlaybackStatus", status.name) | ||
} | ||
|
||
override fun PlayPause() { | ||
println("PlayPause called") | ||
if(status == PlaybackStatus.Playing) | ||
updateStatus(PlaybackStatus.Paused) | ||
else | ||
updateStatus(PlaybackStatus.Playing) | ||
} | ||
|
||
override fun Play() { | ||
println("Play called") | ||
updateStatus(PlaybackStatus.Playing) | ||
} | ||
|
||
override fun Pause() { | ||
println("Pause called") | ||
updateStatus(PlaybackStatus.Paused) | ||
} | ||
|
||
override fun Stop() { | ||
println("Stop called") | ||
updateStatus(PlaybackStatus.Stopped) | ||
} | ||
|
||
override fun Seek(x: Long) { | ||
println("Seeking by $x") | ||
} | ||
|
||
override fun Previous() { | ||
println("Previous called") | ||
} | ||
|
||
override fun Next() { | ||
println("Next called") | ||
} | ||
|
||
override fun Raise() { | ||
println("open me!") | ||
} | ||
|
||
override fun Quit() { | ||
println("I'm quitting!") | ||
conn.disconnect() | ||
} | ||
|
||
override fun OpenUri(uri: String) { | ||
println("OpenUri called") | ||
} | ||
|
||
override fun getObjectPath() = "/org/mpris/MediaPlayer2" | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package xerus.mpris | ||
|
||
import org.freedesktop.dbus.Variant | ||
import java.util.HashMap | ||
|
||
class PropertyMap(initial: PropertyMap.() -> Unit): HashMap<String, Variant<*>>() { | ||
|
||
init { | ||
initial(this) | ||
} | ||
|
||
fun put(key: String, value: Any) { | ||
var v = value | ||
if(value is Enum<*>) | ||
v = value.name | ||
super.put(key, Variant(v)) | ||
} | ||
|
||
} |