User Tools

Site Tools


Sidebar

Network and communication

k24:k24.9:k24.9.5:k24.9.5.1:start

24.9.5.1 Project 1 - DBusObserver - Part 1

In the presented program it should be determined whether a USB stick was inserted, which name (label) the USB stick has and under which path the USB stick can be reached.

If you want to develop a project for a D-Bus Observer that is to observe a method or a signal, you must obtain the answers to the following questions in advance:

  • Which d-bus-enabled application sends the message to be intercepted?
  • Is the method or signal sent on the session bus or on the system bus?
  • Which type represents the message?
  • Which D-Bus object is used?
  • Is the object path known?
  • What is the name of the method or the signal to be observed (member)?
  • What is the signature of the message?
  • What is the name of the interface - if one exists?

The answers to the questions can be given if you use the two programs d-feet and dbus-monitor and carefully analyze their output when inserting a USB stick with regard to the above-mentioned task. The use of the d-feet program is presented in the chapter D-Bus introspection.

The console program dbus-send is also very useful for introspection:

$ dbus-send --session --print-reply –dest=org.gtk.Private.UDisks2VolumeMonitor \
 /org/gtk/Private/RemoteVolumeMonitor \
 org.freedesktop.DBus.Introspectable.Introspect > volumemonitor.introspection.xml

Here is an excerpt from the XML file:

...
  <signal name="VolumeAdded">
    <arg type="s" name="dbus_name"/>
    <arg type="s" name="id"/>
    <arg type="(ssssssbbssa{ss}sa{sv})" name="volume"/>
  </signal>
...

This is supplemented by a section of the output of the dbus-monitor program when a USB stick is inserted and, among other things, the “VolumeAdded” D-Bus signal of the /org/gtk/Private/RemoteVolumeMonitor object that is then triggered is displayed with the values of its arguments:

signal sender=:1.10 -> dest=(null destination) serial=53 path=/org/gtk/Private/RemoteVolumeMonitor;
   interface=org.gtk.Private.RemoteVolumeMonitor; member=VolumeAdded
   string "org.gtk.Private.UDisks2VolumeMonitor"
   string "0x2493c70"
   struct {
      string "0x2493c70"
      string "2_GB_P"
      string ". GThemedIcon drive-removable-media-usb drive-removable-media drive-removable drive"
      string ". GThemedIcon drive-removable-media-usb-symbolic ... drive-removable drive"
      string ""
      string ""
      boolean true
      boolean true
      string "0x24b4d90"
      string ""
      array [
         dict entry(
            string "class"
            string "device"
         )
         dict entry(
            string "unix-device"
            string "/dev/sdd1"
         )
         dict entry(
            string "label"
            string "2_GB_P"
         )
         dict entry(
            string "uuid"
            string "38ea6e0b-a161-401d-a673-11c06cf1229e"
         )
      ]
      string "gvfs.time_detected_usec.1519387042284411"
      array [
      ]
   }

Thus and also after a look into the editions of the console program d-feet the following concrete answers for the correct application resulted:

  • Application (D-Bus name): org.gtk.Private.UDisks2VolumeMonitor
  • D-Bus: Session Bus
  • Type of message: Signal
  • D-Bus object path: /org/gtk/Private/RemoteVolumeMonitor
  • Name of the signal (Member): VolumeAdded
  • The message has three arguments. The signature can be read from the section above from the XML file. Argument1: String, Argument2: String, Argument3: ComplexType
  • Name of the interface: org.gtk.Private.UDisks2VolumeMonitor

24.9.5.1.1 Signature of the signal 'VolumeAdded'

The following section on the signal called “VolumeAdded” from the very extensive content of the XML document is interesting with regard to the task described above:

<signal name="VolumeAdded">
  <arg type="s" name="dbus_name"/>
  <arg type="s" name="id"/>
  <arg type="(ssssssbbssa{ss}sa{sv})" name="volume"/>
</signal>

The following can be noted:

  • The signal has a name that points in the right direction - VolumeAdded
  • The signal has exactly three arguments.
  • A (data) type is specified for each argument.
  • Each argument has a name.

To describe the number and types of arguments required by methods and signals, D-Bus uses a string coding in the form of signatures.

  • The arguments Arg1 and Arg2 have the native data type String.
  • Argument 3 has a complex data type: 6 consecutive strings can be read, followed by 2 logical values. Then come two more strings. These strings are followed by a collection (Collection1 with KeyTyp = String and DataTyp = String). Collection1 is followed by a string followed by another collection (Collection2 with KeyTyp = String and DataTyp = Variant).

A simple and expressive format! Now it becomes interesting for the project DBusObserver1 how the data types of the 3rd argument can be mapped to a complex data type in Gambas. Correct - there is an easy way to do this by using the data type Struct:

Public Struct StructVariant
  String1 As String
  String2 As String
  String3 As String
  String4 As String
  String5 As String
  String6 As String
  Boolean1 As Boolean
  Boolean2 As Boolean
  String7 As String
  String8 As String
  Collection1 As Collection
  String9 As String
  Collection2 As Collection
End Struct

Public structSignalArgument3 As New StructVariant

24.9.5.1.2 Project 1 - Part 2

The source code for the project is manageable, is therefore fully specified and then commented on:

[1] ' Gambas class file
[2]
[3] Public Struct StructVariant
[4]   String1 As String
[5]   String2 As String
[6]   String3 As String
[7]   String4 As String
[8]   String5 As String
[9]   String6 As String
[10]   Boolean1 As Boolean
[11]   Boolean2 As Boolean
[12]   String7 As String
[13]   String8 As String
[14]   Collection1 As Collection
[15]   String9 As String
[16]   Collection2 As Collection
[17] End Struct
[18]
[19] Public structSignalArgument3 As New StructVariant
[20] Public hDBusObserver As DBusObserver
[21]
[22] Private $cDBus As DBusConnection
[23] Private $iOSMessageType As Integer
[24] Private $sOSObjectPath As String
[25] Private $sOSMember As String
[26] Private $sOSInterface As String
[27] Private $sOSDestination As String
[28]
[29] Public Sub Form_Open()
[30]
[31]   FMain.Resizable = True
[32]
[33]   $cDBus = DBus.Session
[34]   $iOSMessageType = DBus.Signal
[35]   $sOSObjectPath = "/org/gtk/Private/RemoteVolumeMonitor"
[36]   $sOSMember = "VolumeAdded" ' Member -> DBus-SignalName
[37]   $sOSInterface = "org.gtk.Private.RemoteVolumeMonitor"
[38]   $sOSDestination = "*"
[39]
[40]   hDBusObserver = New DBusObserver($cDBus, $iOSMessageType, $sOSObjectPath, $sOSMember, $sOSInterface, $sOSDestination) As "hDBusObserver"
[41]
[42]   FMain.Caption = "DBus-Observer:  Signal" & " ==> " & $sOSMember
[43]
[44] End
[45]
[46] Public Sub hDBusObserver_Message()
[47]
[48]   Dim k As Integer = 1
[49]   Dim vElement As Variant
[50]   Dim aArguments As Variant[]
[51]   Dim sDestination As String
[52]   Dim aObserverMessageTypes As String[] = ["DBus.Method", "DBus.Reply", "DBus.Error", "DBus.Signal"]
[53]
[54]   aArguments = hDBusObserver.Message.Arguments
[55]
[56]   structSignalArgument3.String1 = aArguments[2][0]
[57]   structSignalArgument3.String2 = aArguments[2][1]
[58]   structSignalArgument3.String3 = aArguments[2][2]
[59]   structSignalArgument3.String4 = aArguments[2][3]
[60]   structSignalArgument3.String5 = aArguments[2][4]
[61]   structSignalArgument3.String6 = aArguments[2][5]
[62]   structSignalArgument3.Boolean1 = aArguments[2][6]
[63]   structSignalArgument3.Boolean2 = aArguments[2][7]
[64]   structSignalArgument3.String7 = aArguments[2][8]
[65]   structSignalArgument3.String8 = aArguments[2][9]
[66]   structSignalArgument3.Collection1 = aArguments[2][10]
[67]   structSignalArgument3.String9 = aArguments[2][11]
[68]   structSignalArgument3.Collection2 = aArguments[2][12]
[69]
[70]   If Not hDBusObserver.Message.Destination Then
[71]      sDestination = "All Applications"
[72]   Else
[73]      sDestination = hDBusObserver.Message.Destination
[74]   Endif
[75]
[76]   txaResults.Insert(gb.NewLine)
[77]   txaResults.Insert("Message-Destination = " & sDestination & gb.NewLine)
[78]   txaResults.Insert("Message-Interface = " & hDBusObserver.Message.Interface & gb.NewLine)
[79]   txaResults.Insert("Message-Member = " & hDBusObserver.Message.Member & gb.NewLine)
[80]   txaResults.Insert("Message-Object = " & hDBusObserver.Message.Object & gb.NewLine)
[81]   txaResults.Insert("Message-Sender (ID) = " & hDBusObserver.Message.Sender & gb.NewLine)
[82]   txaResults.Insert("Message-Number = " & hDBusObserver.Message.Serial & gb.NewLine)
[83]   txaResults.Insert("Message-Type = " & aObserverMessageTypes[hDBusObserver.Message.Type - 1])
[84]   txaResults.Insert(gb.NewLine & gb.NewLine)
[85]
[86]   txaResults.Insert("Arguments of the \"VolumeAdded\" Signal:" & gb.NewLine)
[87]   txaResults.Insert(String$(61, "-") & gb.NewLine)
[88]   txaResults.Insert("<signal name=\"VolumeAdded\"" & gb.NewLine)
[89]   txaResults.Insert("  <arg type=\"s\" name=\"dbus_name\"/>" & gb.NewLine)
[90]   txaResults.Insert("  <arg type=\"s\" name=\"id\"/>" & gb.NewLine)
[91]   txaResults.Insert("  <arg type=\"(ssssssbbssa{ss}sa{sv})\" name=\"volume\"/>" & gb.NewLine)
[92]   txaResults.Insert("</signal>" & gb.NewLine & gb.NewLine)
[93]
[94]   txaResults.Insert("Number of arguments for Variant-Array 'Arguments' = " & aArguments.Count &
gb.NewLine)
[95]   txaResults.Insert(gb.NewLine)
[96]   txaResults.Insert("String:" & gb.NewLine)
[97]   txaResults.Insert("Arguments[0] = " & aArguments[0] & gb.NewLine)
[98]   txaResults.Insert("String:" & gb.NewLine)
[99]   txaResults.Insert("Arguments[1] = " & aArguments[1] & gb.NewLine)
[100]
[101]   txaResults.Insert("Data-Type Struct:" & gb.NewLine)
[102] ' 6x String
[103]   txaResults.Insert("Arguments[2][0] = " & aArguments[2][0] & gb.NewLine)
[104]   txaResults.Insert("Arguments[2][1] = " & aArguments[2][1] & gb.NewLine)
[105]   txaResults.Insert("Arguments[2][2] = " & aArguments[2][2] & gb.NewLine)
[106]   txaResults.Insert("Arguments[2][3] = " & aArguments[2][3] & gb.NewLine)
[107]   txaResults.Insert("Arguments[2][4] = " & aArguments[2][4] & gb.NewLine)
[108]   txaResults.Insert("Arguments[2][5] = " & aArguments[2][5] & gb.NewLine)
[109] ' 2x Boolean
[110]   txaResults.Insert("Arguments[2][6] = " & aArguments[2][6] & gb.NewLine)
[111]   txaResults.Insert("Arguments[2][7] = " & aArguments[2][7] & gb.NewLine)
[112] ' 2x String
[113]   txaResults.Insert("Arguments[2][8] = " & aArguments[2][8] & gb.NewLine)
[114]   txaResults.Insert("Arguments[2][9] = " & aArguments[2][9] & gb.NewLine)
[115] ' Collection 1 -> KeyType = String and DataType = String
[116]   txaResults.Insert("Collection 1 = Arguments[2][10]" & gb.NewLine)
[117]   If structSignalArgument3.Collection1.Count > 0 Then
[118]      For Each vElement In structSignalArgument3.Collection1
[119]        txaResults.Insert("Element " & Str(k) & "  :   " & structSignalArgument3.Collection1.Key)
[120]        txaResults.Insert(" = " & vElement & gb.NewLine)
[121]        Inc k
[122]      Next
[123]     Else
[124]      txaResults.Insert("Attention: The collection 1 is empty!" & gb.NewLine)
[125]   Endif
[126] ' 1x String
[127]   txaResults.Insert("Arguments[2][11] = " & aArguments[2][11] & gb.NewLine)
[128]   k = 1
[129] ' Collection 2 -> KeyType = String and DataType = Variant
[130]   txaResults.Insert("Collection 2 = Arguments[2][12]" & gb.NewLine)
[131]   If structSignalArgument3.Collection2.Count > 0 Then
[132]      For Each vElement In structSignalArgument3.Collection2
[133]        txaResults.Insert("Element " & Str(k) & "  :   " & structSignalArgument3.Collection2.Key)
[134]        txaResults.Insert(" = " & vElement & gb.NewLine)
[135]        Inc k
[136]      Next
[137]   Else
[138]      txaResults.Insert("Attention: The collection 2 is empty!" & gb.NewLine)
[139]   Endif
[140]
[141] End
[142]
[143] Public Sub Form_Close()
[144]   hDBusObserver = Null
[145]   FMain.Close()
[146] End

Comment:

  • The necessary variables are declared in lines 3 to 27.
  • The arguments for creating a DBusObserver object are assigned in lines 33 to 38.
  • Alternatively you can intercept other signals (DriveConnected, DriveChanged, VolumeChanged, VolumeRemoved, MountAdded, DriveEject, MountPreUnmount, MountChanged). Then you have to find out their signatures for these signals, because a simple exchange of $sOSMember = “VolumeAdded” for $sOSMember = “MountAdded” leads to an error!
  • The message event in line 46 is triggered when the signal to be observed is detected on the D-Bus. The complete message is stored in the properties of the virtual class DBusObserver.Message.
  • In line 54 all three arguments of the property hDBusObserver.Message.argument are stored in a variant array.
  • In lines 56 to 68, the elements of the defined structure (structSignalArgument3) are filled with the values whose data type was previously read from the signature for the third argument.
  • The values of all properties of the class DBusObserver.message - but without the property Arguments of the data type Variant Array are assigned in rows 77 to 84 and displayed in a TextArea.
  • The values of argument 1 and argument 2 of the property Argument are displayed in lines 97 and 99. Then the values of the complex argument 3 are displayed in the lines from 102.

The result of observing the “VolumeAdded” signal of the org.gtk.Private.UDisks2VolumeMonitor object is impressive:

Figure 24.9.5.1.1: Evaluation of the observation of the'VolumeAdded' signal (Message-Member)

You can adapt the presented project to other messages to be observed. However, you can only do this without any problems if you carefully run the introspection again for the selected message type with the recommended programs, in order to determine the signature of the messages, among other things.

24.9.5.1.3 Project 2 - ObserverDBus - Signal 'MountAdded'

In another project, an Observer for the 'MountAdded' signal will be made available to you for testing. The data type Struct is omitted and only the Gambas data types Integer, String, Array and Collection are used, as a look at the definition list shows:

Dim k As Integer = 1
Dim vElement As Variant
Dim cCollection As Collection
Dim aArray As String[]
Dim aArguments As Variant[]
Dim sDestination As String
Dim aObserverMessageTypes As String[] = ["DBus.Method", "DBus.Reply", "DBus.Error", "DBus.Signal"]

The signature of the message - compared to project 1 - is completely different:

<signal name="MountAdded">
  <arg type="s" name="dbus_name"/>
  <arg type="s" name="id"/>
  <arg type="(ssssssbsassa{sv})" name="mount"/>
</signal>

This is the output when the'MountAdded' signal has been intercepted and evaluated:

Figure 24.9.5.1.2: Evaluation of the observation of the 'MountAdded' signal

Chapter 24.9.8.0 introduces the two classes DBusVariant and DBusValues, with which you can create the appropriate, dbus-compatible data for your own messages for self-declared signatures from the data with Gambas data types. Two projects, in which Gambas programs (server/client) export D-Bus objects and offer or use services, supplement the described theory.

Download

This website uses cookies. By using the website, you agree with storing the cookies on your computer. More information in the privacy policy.
k24/k24.9/k24.9.5/k24.9.5.1/start.txt · Last modified: 02.07.2018 (external edit)

Page Tools