muka / go-bluetooth

Golang bluetooth client based on bluez DBus interfaces
Apache License 2.0
652 stars 125 forks source link

MediaPlayer1.GetTrack: interface {} is map[string]dbus.Variant, not map[string]interface {} #133

Closed demitriusbelai closed 2 years ago

demitriusbelai commented 3 years ago

Hi! I am trying to get Track from ARVCP using MediaPlayer1. Unfortunately that is giving error:

panic: interface conversion: interface {} is map[string]dbus.Variant, not map[string]interface {}

goroutine 1 [running]:
github.com/muka/go-bluetooth/bluez/profile/media.(*MediaPlayer1).GetTrack(0xc0000768d0, 0x2d, 0xc0000768d0, 0x0)
        /home/demitrius/go/pkg/mod/github.com/muka/go-bluetooth@v0.0.0-20201211051136-07f31c601d33/bluez/profile/media/gen_MediaPlayer1.go:479 +0xd9
main.main()
        /home/demitrius/source/go-bluetooth-test/teste/bluetooth.go:16 +0xf8
exit status 2

This is my code:

mediaPlayer, err := media.NewMediaPlayer1("/org/bluez/hci0/dev_50_92_B9_03_CA_4B/player0")
if err != nil {
    return
}
v, err := mediaPlayer.GetTrack()

Using MediaPlayer1.GetProperty and converting to map[string]dbus.Variant works:

v, err := mediaPlayer.GetProperty("Track")
if err != nil {
    fmt.Fprintln(os.Stderr, "Error getting Track", err)
}
values := v.Value().(map[string]dbus.Variant)
fmt.Printf("%v %T\n", values, values)

System

OS: Arch Linux GO: go version go1.16.3 linux/amd64

muka commented 3 years ago

Hi, the code probably generates with the wrong signature. Which version of bluez are you using?

demitriusbelai commented 3 years ago

In Arch I am using Bluez 5.58. I also tried Ubuntu 20.04 with Bluez 5.53 and I got the same error.

I did not known it was generate. I inspected the source and I found this:

diff --git a/gen/generator/generator_types.go b/gen/generator/generator_types.go
index 8660f74..dfec72b 100644
--- a/gen/generator/generator_types.go
+++ b/gen/generator/generator_types.go
@@ -21,8 +21,8 @@ func toType(t string) string {
        case "uint8_t":
                return "uint8"
        case "dict":
-               // return "map[string]dbus.Variant"
-               return "map[string]interface{}"
+               return "map[string]dbus.Variant"
+               // return "map[string]interface{}"
        // check in media-api
        case "properties":
                return "string"

Now it works. I guess there are type dict need to be mapped to map[string]interface{} instead of map[string]dbus.Variant. So I tried to put a override instead but It does not work:

diff --git a/gen/override/properties.go b/gen/override/properties.go
index d92ac3f..44c9ea6 100644
--- a/gen/override/properties.go
+++ b/gen/override/properties.go
@@ -12,6 +12,9 @@ var PropertyTypes = map[string]map[string]string{
                "ServiceData":      "map[string]interface{}",
                "ManufacturerData": "map[uint16]interface{}",
        },
+       "org.bluez.MediaPlayer1": {
+               "Track":            "map[string]dbus.Variant",
+       },
        "org.bluez.GattCharacteristic1": {
                "Value":          "[]byte `dbus:\"emit\"`",
                "Descriptors":    "[]dbus.ObjectPath",

Here the log:

DEBU[0000] RAWTYPE org.bluez.MediaPlayer1 Equalizer = string (RAW: string) 
DEBU[0000] RAWTYPE org.bluez.MediaPlayer1 Repeat = string (RAW: string) 
DEBU[0000] RAWTYPE org.bluez.MediaPlayer1 Shuffle = string (RAW: string) 
DEBU[0000] RAWTYPE org.bluez.MediaPlayer1 Scan = string (RAW: string) 
DEBU[0000] RAWTYPE org.bluez.MediaPlayer1 Status = string (RAW: string) 
DEBU[0000] RAWTYPE org.bluez.MediaPlayer1 Position = uint32 (RAW: uint32) 
DEBU[0000] RAWTYPE org.bluez.MediaPlayer1 Track = map[string]interface{} (RAW: map[string]interface{}) 
DEBU[0000] RAWTYPE org.bluez.MediaPlayer1 Title = string (RAW: string) 
DEBU[0000] RAWTYPE org.bluez.MediaPlayer1 Artist = string (RAW: string) 
DEBU[0000] RAWTYPE org.bluez.MediaPlayer1 Album = string (RAW: string) 
DEBU[0000] RAWTYPE org.bluez.MediaPlayer1 Genre = string (RAW: string) 
DEBU[0000] RAWTYPE org.bluez.MediaPlayer1 NumberOfTracks = uint32 (RAW: uint32) 
DEBU[0000] RAWTYPE org.bluez.MediaPlayer1 TrackNumber = uint32 (RAW: uint32) 
DEBU[0000] RAWTYPE org.bluez.MediaPlayer1 Duration = uint32 (RAW: uint32) 
DEBU[0000] RAWTYPE org.bluez.MediaPlayer1 Device = dbus.ObjectPath (RAW: dbus.ObjectPath) 
DEBU[0000] RAWTYPE org.bluez.MediaPlayer1 Name = string (RAW: string) 
DEBU[0000] RAWTYPE org.bluez.MediaPlayer1 Type = string (RAW: string) 
DEBU[0000] RAWTYPE org.bluez.MediaPlayer1 Subtype = string (RAW: string) 
DEBU[0000] RAWTYPE org.bluez.MediaPlayer1 Browsable = bool (RAW: bool) 
DEBU[0000] RAWTYPE org.bluez.MediaPlayer1 Searchable = bool (RAW: bool) 
DEBU[0000] RAWTYPE org.bluez.MediaPlayer1 Playlist = dbus.ObjectPath (RAW: dbus.ObjectPath) 
DEBU[0000] props --> Track map[string]dbus.Variant      
TRAC[0000] Wrote bluez/profile/media/gen_MediaPlayer1.go 

Did I miss something?

demitriusbelai commented 3 years ago

This fixes the issue:

diff --git a/gen/generator/generator_tpl_api.go b/gen/generator/generator_tpl_api.go
index a5aa8e5..24785ea 100644
--- a/gen/generator/generator_tpl_api.go
+++ b/gen/generator/generator_tpl_api.go
@@ -74,9 +74,9 @@ func ApiTemplate(filename string, api *types.Api, apiGroup *types.ApiGroup) erro
                        var prop *types.PropertyDoc
                        if _, ok := propsList[propName]; ok {
                                prop = propsList[propName]
+                               prop.Property.Type = propType
                                prop.RawType = getRawType(prop.Property.Type)
                                prop.RawTypeInitializer = getRawTypeInitializer(prop.Property.Type)
-                               prop.Property.Type = propType
                                // log.Debugf("props --> %s %s", propName, propType)
                        } else {
                                prop = &types.PropertyDoc{
diff --git a/gen/override/properties.go b/gen/override/properties.go
index d92ac3f..44c9ea6 100644
--- a/gen/override/properties.go
+++ b/gen/override/properties.go
@@ -12,6 +12,9 @@ var PropertyTypes = map[string]map[string]string{
                "ServiceData":      "map[string]interface{}",
                "ManufacturerData": "map[uint16]interface{}",
        },
+       "org.bluez.MediaPlayer1": {
+               "Track":            "map[string]dbus.Variant",
+       },
        "org.bluez.GattCharacteristic1": {
                "Value":          "[]byte `dbus:\"emit\"`",
                "Descriptors":    "[]dbus.ObjectPath",

However it makes changes in others classes listed in override package. I do not know if that was already wrong.

muka commented 2 years ago

Hi, a bit late I think but got time to check. For those types I usually add a dedicated struct in the output package and map it directly. If you have a chance to try, let me know! Thanks