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

Get list of available config OOP #30

Closed
birkanozer opened this issue Apr 15, 2017 · 5 comments
Closed

Get list of available config OOP #30

birkanozer opened this issue Apr 15, 2017 · 5 comments
Labels

Comments

@birkanozer
Copy link

Hi Jim,

I want to list all available config options like camera-gui-config-oop.py file by using oop stracture. I inspected codebase but I'm not expert on C or SWIG. I tried camera.get_config(context) and it returns a SWIG object. How can i convert it to list or dict of possible values?

@jim-easterbrook
Copy link
Owner

jim-easterbrook commented Apr 15, 2017

The object returned by camera.get_config is a 'widget' (the name libgphoto2 uses) that is the root of the config tree structure. It has methods such as config.count_children to get the number of child widgets and config.get_child to get a particular child. The widget layout varies with camera type, but is unlikely to be a simple list or dict, unless you use 'compound' keys such as settings.autopoweroff for the autopoweroff child of the settings node.

The 'leaf' nodes on the tree have methods like config.get_value to get the actual camera settings.

PS sorry about the earlier (deleted) reply - I hadn't read your question properly.

@birkanozer
Copy link
Author

Thanks for the answer. Here is a working example based on your description:

import gphoto2 as gp

context = gp.Context()
camera = gp.Camera()
camera.init(context)
config_tree = camera.get_config(context)
print('=======')

total_child = config_tree.count_children()
for i in range(total_child):
    child = config_tree.get_child(i)
    text_child = '# ' + child.get_label() + ' ' + child.get_name()
    print(text_child)

    for a in range(child.count_children()):
        grandchild = child.get_child(a)
        text_grandchild = '    * ' + grandchild.get_label() + ' -- ' + grandchild.get_name()
        print(text_grandchild)

        try:
            text_grandchild_value = '        Setted: ' + grandchild.get_value()
            print(text_grandchild_value)
            print('        Possibilities:')
            for k in range(grandchild.count_choices()):
                choice = grandchild.get_choice(k)
                text_choice = '         - ' + choice
                print(text_choice)
        except:
            pass
        print()
    print()

camera.exit(context)

@jim-easterbrook
Copy link
Owner

Never, ever, do this:

except:
    pass

Remember that SyntaxError is an exception which you are now ignoring. That makes fixing errors in your code more difficult. Be as specific as you can about the exceptions you want to catch and let others (the unexpected ones) propagate as normal.

@birkanozer
Copy link
Author

Thanks for the advice ;)

@M4lF3s
Copy link

M4lF3s commented Jul 29, 2022

Hi 👋

Sorry I just stumbled across this Thread and wanted to chip in my solution, since I wanted to do a similar thing (I think).
Now I know that this is by far not a perfect solution, since as Jim already mentioned the Structure of the Configuration Tree may very well vary from Camera to Camera. In my particular case I am using a Canon EOS M6 Mark II, but I thought maybe this is helpful for others too.

Now if you´re only interested in the actual Configuration Parameters and their values, you don´t really need the Information about the Hierarchy in between the Nodes. Only the Leafs and their Values.

So for that you can parse the Config into a nice little Dictionary like so:

config_leafs = {config_tree.get_child(i).get_child(a).get_name(): config_tree.get_child(i).get_child(a).get_value() for i in range(config_tree.count_children()) for a in range(config_tree.get_child(i).count_children())}

which would result in a dict like this:

{
  'syncdatetimeutc': 0, 
  'syncdatetime': 0, 
  'uilock': 2,
  ...
}

But if you actually want to preserve the Hierarchy Information I came up with this monstrosity:

config = {
  child.get_name(): dict(
    label=child.get_label(),
    **{grandchild.get_name(): {
      'label': grandchild.get_label(),
      'set_value': grandchild.get_value(),
      'possible_values': grandchild.get_type()==gp.GP_WIDGET_RADIO or grandchild.get_type()==gp.GP_WIDGET_MENU and [grandchild.get_choice(k) for k in range(grandchild.count_choices())] or []
    } for grandchild in [child.get_child(a) for a in range(child.count_children())]}
  ) for child in [config_tree.get_child(i) for i in range(config_tree.count_children())]
}

This actually gives you a dict like this:

{
  <child_name>: {
    'label': <child_label>,
    <grandchild_name>: {
      'label': <grandchild_label>,
      'set_value': <grandchild_value>,
      'possible_values': [<grandchild_choice(1)>, <grandchild_choice(2)>, ...]
    },
    ...
  },
  ...
}

The Problem with the 'possible_values' is that they only exist in some 'grandchild Nodes'. I guess that was the reason for the except: pass part. But the Documentation of libgphoto2 states that count_choices() and get_choice() should be avaibable for Camera Widgets of type GP_WIDGET_RADIO and GP_WIDGET_MENU. Hence the wild Logic Operations there 😅 (I just learned that this technique is actually called "short circuiting" 👍 )

Now like I said. This is by no means a perfect solution. And since I am really neither a Expert in Python nor in the underlying C I can´t actually decide if I find this code really cool or totally unmaintainable 😄 (maybe both) but I figured since I already took the time I would just share the results in case it helps someone else too 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants