Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Request: Add support for multiple tablets #17

Closed
jcpearson opened this issue Aug 1, 2018 · 14 comments
Closed

Feature Request: Add support for multiple tablets #17

jcpearson opened this issue Aug 1, 2018 · 14 comments

Comments

@jcpearson
Copy link

I had a go at allowing the GUI to support multiple tablets - and have come up with the patch below

If multiple tablets are found, then it prompts for for which tablet to use - however, I have no idea how to do this with PyQt4 - so I've just used zenity :-)

This patch has the side effect of replacing the code causing the problem with issue #15

--- ./wacom-gui/pad.py.dist     2018-07-31 12:05:57.344886918 +0100
+++ ./wacom-gui/pad.py  2018-08-01 14:02:27.260979779 +0100
@@ -24,7 +24,7 @@ class Pad(QtGui.QWidget):
         
     def initUI(self):
         #get tablet name/type
-        tablets = os.popen("lsusb | grep -i wacom").readlines()
+        tablets = os.popen("lsusb -d 056a:").readlines()
         self.TabletIds = tabletidentities()
         # reset button configs button
         self.buttonReset = QtGui.QPushButton("Reset Buttons")
@@ -39,43 +39,70 @@ class Pad(QtGui.QWidget):
             w.show()
             sys.exit(-1)
         else:
+            # we have at least one Wacom USB ID - extact the details of
+            # the tablets we know about - if we don't know about one
+            # (or more) then save this as a generic tablet
             self.Tablet = []
-            for idx, tablet in enumerate(tablets):
+            for tablet in tablets:
                 (VendId, DevId) = tablet.split(" ")[5].split(":")
-                self.Tablet.append(self.IdentifyByUSBId(VendId, DevId))
-                if self.Tablet[idx].Model != "generic":
-                    self.Tablet[idx].devID = DevId
+                item = self.IdentifyByUSBId(VendId, DevId)
+                if item.Model != "generic":
+                    item.devID = DevId
+                    self.Tablet.append(item)
                 else:
-                    self.Tablet[idx].devID = "generic"
-                    # break
-            # if we have multiple tablets, need to figure out which one we use...
-            if self.Tablet.__len__() != 1:
-                # check of "generic" tablet exists, if it does we ignore it
-                gen_idx = []
-                for idx, dev in enumerate(self.Tablet):
-                    if dev.Model == 'generic':
-                        gen_idx.append(idx)
-                # make sure we have at least 1 tablet detected...
-                if gen_idx.__len__() < self.Tablet.__len__():
-                    gen_idx = sorted(gen_idx)
-                    count = 0
-                    for idx in gen_idx:
-                        self.Tablet.pop(idx - count)
-                if self.Tablet.__len__() > 1:
-                    label = "Multiple Tablets detected; using the first one detected: %s (%s)" % \
-                        (self.Tablet[0].Name, self.Tablet[0].Model)
-                    w = QtGui.QMessageBox()
-                    QtGui.QMessageBox.warning(w, "Information", label)
-                    w.show()
-            self.Tablet = self.Tablet[0]
+                    item.devID = "generic"
+                    genericTablet = item
+
+            # Default index in the found Tablet array
+            idx = 0
+
+            tlen = self.Tablet.__len__()
+            if tlen == 0:
+                # we have a Wacom USB ID - but don't know about the tablet
+                # so we default to a 'generic' tablet
+                self.Tablet.append(genericTablet)
+            elif tlen != 1:
+                # we have multiple tablets, need to figure out which one we use
+                # Hack! - use zenity to prompt for a tablet to select
+                # needs to be replaced with QtPy code ...
+                cmd = "zenity  --list  --title \"Select Tablet to use\" --text \"Select Tablet to use\"  --radiolist  --column \"Select\" --column \"Tablet\" TRUE \"%s\" " % self.Tablet[0].Name
+                for x in range(1, tlen):
+                    cmd += "FALSE \"%s\" " % self.Tablet[x].Name
+                cmd += "2>/dev/null"
+                #print cmd
+                ret = os.popen(cmd).read().rstrip()
+                # if 'Cancel' was selected, then exit here
+                if ret == "":
+                    sys.exit(-1)
+
+                # find the selected tablet
+                for i,tablet in enumerate(self.Tablet):
+                    if tablet.Name == ret:
+                        idx = i
+                        break;
+
+            self.Tablet = self.Tablet[idx]
+            ProductId = self.Tablet.ProductId
+
             # on some tablets each 'device' has a different name ...
             # read in wacom devices into an dict
             deviceNames = {'eraser': None, 'stylus': None, 'cursor': None, 'pad': None, 'touch': None}
             foundDevs = False
+
+            # If we have multiple tablets, then we have to check that the
+            # Wacom devices found by 'xsetwacom --list' are for the tablet
+            # we have selected - this can be checked using the xsetwacom
+            # 'TabletID' option that returns the USB ProductId
+            # If the tablet is 'generic', then we just accept the devices
+            # as is - we use '0xFF' as the ProductId in this case
             with os.popen("xsetwacom --list devices") as f:
                 for line in f:
-                    deviceNames[line.strip().rsplit(" ", 1)[1].lower()] = line.split("\t")[0].strip().rsplit(" ", 1)[0].rstrip()
-                    foundDevs = True
+                    id = line.split("id:")[1].split()[0]
+                    cmd = "xsetwacom --get %s TabletID" % id
+                    ret = os.popen(cmd).read().rstrip()
+                    if ProductId == 0xFF or ProductId == int(ret):
+                        deviceNames[line.strip().rsplit(" ", 1)[1].lower()] = line.split("\t")[0].strip().rsplit(" ", 1)[0].rstrip()
+                        foundDevs = True
 
             if not foundDevs:
                 label = "Tablet not supported"
@jcpearson
Copy link
Author

Note - I'm not sure using two (or more) identical tablets will work as expected - as AFAIK there is no way to distinguish which Wacom devices map to which particular tablet ...

@jcpearson
Copy link
Author

I noticed that the 'touch' device on a "Cintiq Pro 16" is on a different USB ID than the 'stylus' and 'eraser' devices

The libwacom '.tablet' files refers to these 2nd USB IDs as 'PairedIDs' - so I've re-done my multiple tablet patch by taking these into account - which appears to work ...

(I also didn't realise I could attach patches to these issues ...)

New Patch:

multiple-tablets-v2.patch.gz

@tb2097
Copy link
Owner

tb2097 commented Aug 30, 2018

Can you please run /usr/bin/libwacom-list-local-devices for the Cintiq Pro 16 and let me know what the output shows as? I'm thinking this might be a cleaner way to detect the tablets. I didn't know this command existed...

@jcpearson
Copy link
Author

I had actually considered suggesting that you might want to use the libwacom utilities/data files with wacom-gui - it would certainly make it 'easier' to support newer models - and it also comes with svg 'images' of the button layouts - the svg files also contain info about the buttons/controls/etc on the tablet - although I guess it would be a lot of work to convert wacom-gui to use libwacom ? - and that you would also have to supply the 'latest' version and not reply on the older version shipped with the OS ?

Using list-devices (see issue #20) gives for the Cintiq Pro 16:

[Device]
Name=Wacom Cintiq Pro 16
DeviceMatch=usb:056a:0350;
PairedID=usb:056a:0354;
Class=Cintiq
Width=14
Height=8
IntegratedIn=Display;
Styli=0x842;0x84a;0x160802;0x16080a;0x100802;0x10080a;0x140802;0x14080a;0x120802;0x100804;0x10080c;0x100902;0x10090a;0x80842;

[Features]
Reversible=false
Stylus=true
Ring=false
Ring2=false
Touch=true
TouchSwitch=false
StatusLEDs=
NumStrips=0
Buttons=0

@tb2097
Copy link
Owner

tb2097 commented Sep 10, 2018

Given I'd prefer to have people able to swap between multiple tablets without needing to reload the GUI and using libwacom-data for the information this is a significantly bigger rewrite than originally planned for. It's going to be a little bit before I get the pieces in a working state for people to test.

@jcpearson
Copy link
Author

OK - let me know if you need help testing when you have something

@tb2097
Copy link
Owner

tb2097 commented Sep 21, 2018

GUI rework in progress:

  • new GUI in place; supports multiple tablets and refreshing of tablet list if you are connecting/disconnecting tablets. This is done by tracking tablet device ID as supplied by xsetwacom rather than name
  • uses information from libwacom (latest release data will be included in RPM) for correct tablet information, hopefully to streamline device support.
  • layout is effectively aping the layout of the official wacom settings app to hopefully make usage a little clearer
  • multiple tablets of the same kind are detected correctly now, however they will use the same config file
  • multiple configs are possible, however will be disabled until the rest of the GUI is on par (or at least close) to original GUI
  • currently rewriting the tool classes to support using IDs vs device name

I don't have an ETA for a public alpha release yet, but just wanted to provide an update so you know stuff is in the works.

@jcpearson
Copy link
Author

Thanks for the progress report

@tb2097
Copy link
Owner

tb2097 commented Oct 29, 2018

Still in progress... given the rework I decided to try and fix other things that were rather hack-y with how the GUI is working. If you check out the gui-rebuild branch you can test out the new hotkey programming widget.

@tb2097
Copy link
Owner

tb2097 commented Nov 6, 2018

Express Key programming has been reworked. You now select the keypresses from a list, generate your own keystroke commands, as well as add keyboard shortcuts to run commands.

Image of Express Keys Programming

@tb2097
Copy link
Owner

tb2097 commented Nov 17, 2018

I've done some tweaks to the Express Keys display and now have the Stylus programming updated as well. I still need to do some tweaking for the pressure curve, and to implement the mapping, and update config writing to match the new format, but it's ~70% up to spec with the old GUI.
Image of Stylus Programming
Image of Express Keys Programming

@tb2097
Copy link
Owner

tb2097 commented Nov 22, 2018

@jcpearson
Copy link
Author

I haven't had time to look at this yet - but the changes (and images) look good ... thanks!

@tb2097
Copy link
Owner

tb2097 commented Jan 2, 2019

Closing this issue as the feature is now part of the 3.0.x release series. If any issues arise with the feature please open a new ticket.

@tb2097 tb2097 closed this as completed Jan 2, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants