Comments (14)
Check out the recently released mrv2 v0.6.3 where the plug-in system is in place!
from mrv2.
I fixed the printing of Python stdout / stderr to happen as the script runs.
from mrv2.
Currently you can run a python script from the command-line with:
mrv2 -ps <script.py> or mrv2 -pythonScript <script.py>
The script will run without opening a window and it will then exit mrv2. You currently cannot pass any parameters to this script (and I am not sure if it can be done).
You can also add custom scripts to the Python Panel. You open the Python Panel, go to Scripts in the Python Panel menu and you can then pick a script from the file system. The script will be added to the Scripts menu and will get saved in the mrv2.prefs file in your home directory. You can, currently, have up to 10 scripts stored this way. Your idea of using an environment variable is interesting and will require some more work.
Regarding PySide2, mrv2 is built with FLTK, while PySide2 is Qt based. As such, if you open a PySide2 window, you may need to start and control the Qt event loop yourself with (I believe) app.exec_. While the Qt event loop runs, the FLTK event loop (ie. mrv2's playback) will, I believe, remain frozen unless you call cmd.update() (Like it is shown in the timeline.py python demo).
from mrv2.
I noticed you could pass a python script, but of course it'd just close down directly after. The menu entries don't need to be Qt necessarily, but if there's a Python plug-in system in place which could add menu entries it'd be great. A simple example could be something like (psuedocode of course):
Setting environment variable MRV_PLUGIN_PATH
for search paths for plugins.
Then MRV could search those paths and run the plugins it finds
# Discover all plugins
plugins = []
plugin_paths = os.environ.get("MRV_PLUGIN_PATH", "").split(os.pathsep)
for plugin_path in plugin_paths:
discovered_plugins = discover_plugins(plugin_path)
for plugin in discovered_plugins:
plugins.append(plugin)
# Allow users to enable/disable plugins and store those settings
# so we read the preferences to see the preferred state
for plugin in plugins:
if get_plugin_load_state(plugin.name, default=plugin.default_load_state):
plugin.load()
Then any loaded plugin could also expose a customize_menu
adding in custom menu entries (or even replacing existing ones?):
class Plugin(MrvPlugin):
name = "MyPlugin"
default_load_state = True
def load(self):
pass
def unload(self):
pass
def customize_menu(self, menus):
"""Customize menus dict by adding your own entries.
Any `dict` becomes a submenu.
Any `list` or `tuple` is expected to be of length 2
containing the label and the python callback on click.
Arguments:
menus (dict): The current menus that can be
altered by the plugin.
Returns:
dict: The altered menus
"""
# Allow to add in custom menu entries
menus["MyMenu"] = [
("Load", self.on_load),
("Manage", self.on_manage)
{"Submenu": [
("Submenu Action", self.on_submenu_action)
]
]
return menus
Likely there's a much better API to define for this, but it's just a quick showcase of what could be done. I believe OpenRV also has a python plugin system which can define custom menu entries, etc.
By building a plugin system like this it might also become trivial to start writing custom annotation tooling through Python as an extension/plugin too.
from mrv2.
Ok. I have the basic plug-in system in place for you to test. It is in main HEAD (if you compile from source).
There's documentation for it in Help->Documentation and click on the Python / Plug-in System. There's one demo script in the python/plug-ins directory of mrv2. It cretes a Python menu, a Python/Playback/Forwards and Python/Playback/Backwards submenus.
Give it a go and I await your feedback.
from mrv2.
Sweet! It's great seeing a prototype. Mostly busy with other stuff on my end these past few days so I'm slow to reply, sorry about that.
Regarding the plugin system, I think we can improve by having MRV itself define the base Plugin class internally, e.g. mrv.plugins.Plugin
so that developers can inherit from it.
class MyPlugin(mrv.plugins.Plugin):
...
The benefit to that is having autocomplete for existing functions and the base plugin class can also itself document its functionality a bit with docstrings/type hints, etc.
The plugin system would then go over the Python files, and find any classes that inherit from mrv.plugins.Plugin
- those are plugins that can be loaded. This also means that technically a single Python file could hold multiple plugins and even custom systems could be build that load plugins dynamically from elsewhere importing it into the namespace of that file. Anyway, that's likely a very complex use case but it opens up ways to consistency.
That also means that e.g. the base class would already implement the active
method returning True by default. Over time that particular method could even expand to get its active state from some stored preferences file. Say each Plugin requires an id
attribute which defines its unique id. (Or we could just use name
for that?)
class Plugin(mrv2.plugins.Plugin):
id = "my_custom_plugin"
Then we could start building a system into MRV which could maybe toggle on/off Plugins based on user preferences where maybe the default active
method does that:
def active(self):
is_active = get_plugin_pref(self.id, "active", default=True)
return is_active
Anyway. Let me try and fiddle with the system that's currently there.
from mrv2.
Did a quick test run. It does seem to work:
It'd be great however if we can define the order of the menu entries ourselves. Now it seems to be a set
in the example plug-in (which is not sorted) and using a list also doesn't work. My example plug-in used for this screenshot is:
class Plugin:
def on_load(self):
print("Load..")
def on_manage(self):
print("Manage..")
def on_library(self):
print("Library..")
def on_workfiles(self):
print("Workfiles..")
def menus(self):
top = "OpenPype"
menu = [
(f"{top}/Load...", self.on_load),
(f"{top}/Manage...", self.on_manage),
(f"{top}/Library...", self.on_library),
(f"{top}/Workfiles...", self.on_workfiles),
(f"{top}/Submenu/Test...", self.on_workfiles),
]
return menu
from mrv2.
It'd be great however if we can define the order of the menu entries ourselves. Now it seems to be a
set
in the example plug-in (which is not sorted) and using a list also doesn't work. My example plug-in used for this screenshot is:
This is also fixed in HEAD.
from mrv2.
The plugin system would then go over the Python files, and find any classes that inherit from
mrv.plugins.Plugin
- those are plugins that can be loaded. This also means that technically a single Python file could hold multiple plugins and even custom systems could be build that load plugins dynamically from elsewhere importing it into the namespace of that file. Anyway, that's likely a very complex use case but it opens up ways to consistency.
Sadly, I think I cannot do that. A Plugin is one per file and has to be named Plugin. I'll investigate more, though.
from mrv2.
Sadly, I think I cannot do that. A Plugin is one per file and has to be named Plugin. I'll investigate more, though.
Ok. I got it working as you wanted. The changes that you requested, the one line bug fix in the python panel, plus the updated docs and demo plug-in are in this beta of v0.6.4:
.exe:
https://mega.nz/file/KOpVWIgI#b1YnuLQC5NdS_DAzhxqhp1OdMJ-cFz_3YCfUSwy4TC0
.zip:
https://mega.nz/file/HGgEAT7R#BFQacTJbdf5r8EqqovCKbyC3zPAM7nlU57WRbqL59YM
from mrv2.
Thanks! Great improvement. Now using the latest docs with the build I came to this test plugin:
from mrv2 import plugin
class MyPlugin(plugin.Plugin):
def on_load(self):
print("Load..")
def on_manage(self):
print("Manage..")
def on_library(self):
print("Library..")
def on_workfiles(self):
print("Workfiles..")
def menus(self):
top = "Testing"
menu = {
f"{top}/Load...": self.on_load,
f"{top}/Manage...": self.on_manage,
f"{top}/Library...": self.on_library,
f"{top}/Workfiles...": self.on_workfiles,
f"{top}/Submenu/Test...": self.on_workfiles
}
return menu
Order is now preserved 👍 and the above works fine.
What stood out to me however was that this didn't work:
import mrv2.plugin
class MyPlugin(mrv2.plugin.Plugin):
...
Erroring with:
ERROR: [python] AttributeError: module 'mrv2' has no attribute 'plugin'
Which seems confusing? Is there something special happening on the imports of the mrv2
python modules?
Anyway, from mrv2 import plugin
works so I guess there's a workaround for now.
Very nice work!
from mrv2.
import mrv2.plugin
This, for some reason, I cannot make it work. Just import mrv2 and use the full name or do a from mrv2 import plugin and use plugin.Plugin.
class MyPlugin(mrv2.plugin.Plugin):
This now works.
from mrv2.
I thought I should mention that v0.7.9 has introduced pyFLTK support. This integrates more seamlessly with mrv2 than PySide2 as it can run within mrv2's event loop (ie. you can have the player playing videos while you interact with your own windows, buttons and requesters). See:
from mrv2.
Regarding PySide2, mrv2 is built with FLTK, while PySide2 is Qt based. As such, if you open a PySide2 window, you may need to start and control the Qt event loop yourself with (I believe) app.exec_. While the Qt event loop runs, the FLTK event loop (ie. mrv2's playback) will, I believe, remain frozen unless you call cmd.update() (Like it is shown in the timeline.py python demo).
I just wanted to mention that it seems like calling cmd.update()
works fine - however it does not update any printed output into MRV2's Python panel top log area. The output doesn't appear until the Qt application loop actually closes down it seems.
from mrv2.
Related Issues (20)
- Image is more saturated than in other video players HOT 13
- v1.1.6 on Linux re-released with a fix to Linux X11 crashes when going to presentation mode.
- Wayland's playback with NVidia EGL drivers can stall (not refresh neither the view window or timeline). HOT 1
- Playlist Failing on macOS arm64 M3 HOT 13
- Linux binary distribution has Gnome incompatibilities with Wayland under modern distros. HOT 2
- The position and the size are not saved HOT 8
- Getting pure white where alpha is 0 using v1.1.8 HOT 9
- Mouse-wheel zoom depends on side panel scroll bar HOT 5
- Load OCIO Config window bug & also a crash and ocio reverting HOT 2
- mrv2 1.1.9 - Installer issues - Strings untranslated
- MRV2 1.1.9 Repeat Frame option clamps values to 1 on the repeated frame. HOT 14
- Video keeps playing even if mouse is not scrubbing on screen anymore HOT 10
- The Ability to Specify Image Sequence Frame Range HOT 6
- Step through collection of unrelated images HOT 3
- v1.2.1 has been re-released on 7/12/2024 to fix a serious crashing bug on saving movies.
- scrub with LMB - stop when mouse stops HOT 4
- EXR maultilayer next/previous channel hotkeys not working HOT 4
- Option to Disable Allways on Top HOT 2
- The Ability to Reload Frame(s) HOT 2
- Installing mrv2 breaks theming in Pop!_OS. HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from mrv2.