Here is the first version I feel comfortable people testing…
copy the code below into blenders text editor and click run
bl_info = {
'name': 'Media Keys',
'author': 'Robert Forsyth',
'version': (0, 0, 1),
'blender': (2, 78, 0),
'location': 'View3D > Tool Panel > Music',
'description': 'Disables Blenders use of Media Keys and adds a menu (good for tablet use)',
'warning': 'Does not disable blenders use of the media keys yet!',
'wiki_url': 'http://blenderartists.org',
'tracker_url': '',
'support': 'COMMUNITY',
'category': '3D View'}
import bpy
import ctypes
from ctypes import wintypes
import time
user32 = ctypes.WinDLL('user32', use_last_error=True)
INPUT_MOUSE = 0
INPUT_KEYBOARD = 1
INPUT_HARDWARE = 2
KEYEVENTF_EXTENDEDKEY = 0x0001
KEYEVENTF_KEYUP = 0x0002
KEYEVENTF_UNICODE = 0x0004
KEYEVENTF_SCANCODE = 0x0008
MAPVK_VK_TO_VSC = 0
# msdn.microsoft.com/en-us/library/dd375731
VK_MEDIA_PLAY_PAUSE = 0xB3
VK_MEDIA_PREV_TRACK = 0xB1
VK_MEDIA_NEXT_TRACK = 0xB0
VK_VOLUME_DOWN = 0xAE
VK_VOLUME_UP = 0xAF
VK_VOLUME_MUTE = 0xAD
# C struct definitions
wintypes.ULONG_PTR = wintypes.WPARAM
class MOUSEINPUT(ctypes.Structure):
_fields_ = (("dx", wintypes.LONG),
("dy", wintypes.LONG),
("mouseData", wintypes.DWORD),
("dwFlags", wintypes.DWORD),
("time", wintypes.DWORD),
("dwExtraInfo", wintypes.ULONG_PTR))
class KEYBDINPUT(ctypes.Structure):
_fields_ = (("wVk", wintypes.WORD),
("wScan", wintypes.WORD),
("dwFlags", wintypes.DWORD),
("time", wintypes.DWORD),
("dwExtraInfo", wintypes.ULONG_PTR))
def __init__(self, *args, **kwds):
super(KEYBDINPUT, self).__init__(*args, **kwds)
# some programs use the scan code even if KEYEVENTF_SCANCODE
# isn't set in dwFflags, so attempt to map the correct code.
if not self.dwFlags & KEYEVENTF_UNICODE:
self.wScan = user32.MapVirtualKeyExW(self.wVk,
MAPVK_VK_TO_VSC, 0)
class HARDWAREINPUT(ctypes.Structure):
_fields_ = (("uMsg", wintypes.DWORD),
("wParamL", wintypes.WORD),
("wParamH", wintypes.WORD))
class INPUT(ctypes.Structure):
class _INPUT(ctypes.Union):
_fields_ = (("ki", KEYBDINPUT),
("mi", MOUSEINPUT),
("hi", HARDWAREINPUT))
_anonymous_ = ("_input",)
_fields_ = (("type", wintypes.DWORD),
("_input", _INPUT))
LPINPUT = ctypes.POINTER(INPUT)
def _check_count(result, func, args):
if result == 0:
raise ctypes.WinError(ctypes.get_last_error())
return args
user32.SendInput.errcheck = _check_count
user32.SendInput.argtypes = (wintypes.UINT, # nInputs
LPINPUT, # pInputs
ctypes.c_int) # cbSize
# Functions
def PressKey(hexKeyCode):
x = INPUT(type=INPUT_KEYBOARD,
ki=KEYBDINPUT(wVk=hexKeyCode))
user32.SendInput(1, ctypes.byref(x), ctypes.sizeof(x))
def ReleaseKey(hexKeyCode):
x = INPUT(type=INPUT_KEYBOARD,
ki=KEYBDINPUT(wVk=hexKeyCode,
dwFlags=KEYEVENTF_KEYUP))
user32.SendInput(1, ctypes.byref(x), ctypes.sizeof(x))
# Add new keys here.
def PlayPause():
PressKey(VK_MEDIA_PLAY_PAUSE)
time.sleep(.2)
ReleaseKey(VK_MEDIA_PLAY_PAUSE)
def PrevTrack():
PressKey(VK_MEDIA_PREV_TRACK)
time.sleep(.2)
ReleaseKey(VK_MEDIA_PREV_TRACK)
def NextTrack():
PressKey(VK_MEDIA_NEXT_TRACK)
time.sleep(.2)
ReleaseKey(VK_MEDIA_NEXT_TRACK)
def VolUp():
PressKey(VK_VOLUME_UP)
time.sleep(.2)
ReleaseKey(VK_VOLUME_UP)
def VdoDo():
PressKey(VK_VOLUME_DOWN)
time.sleep(.2)
ReleaseKey(VK_VOLUME_DOWN)
def Vmute():
PressKey(VK_VOLUME_MUTE)
time.sleep(.2)
ReleaseKey(VK_VOLUME_MUTE)
#if __name__ == "__main__":
# PlayPause()
# ------------------------------------------------------------------------
# Music Menu
# ------------------------------------------------------------------------
class ToolPropsPanel(bpy.types.Panel):
bl_label = "Hello from Tool props"
bl_space_type = "VIEW_3D"
bl_region_type = "TOOLS"
bl_label = "Media Controls"
bl_context = "objectmode"
bl_category = "Music"
def draw(self, context):
layout = self.layout
layout.label("Music Controls")
row = layout.row(align=False)
layout.operator("hello.hello", icon='FILE_SOUND', text='Play/Pause').function = "Play"
row = layout.row(align=False)
row.alignment = 'LEFT'
layout.operator("hello.hello", icon='REW', text='Previous').function = "Prev"
row = layout.row(align=False)
row.alignment = 'LEFT'
layout.operator("hello.hello", icon='FF', text='Next').function = "Next"
layout.label("Volume Controls")
row = layout.row(align=False)
row.alignment = 'LEFT'
layout.operator("hello.hello", icon='PLAY_AUDIO', text='Vol Up').function = "Vup"
row = layout.row(align=False)
row.alignment = 'LEFT'
layout.operator("hello.hello", icon='PLAY_AUDIO', text='Vol Down').function = "Vdown"
row = layout.row(align=False)
row.alignment = 'LEFT'
layout.operator("hello.hello", icon='X_VEC', text='Toggle Mute').function = "Vmute"
class Button_Of_Good_Music(bpy.types.Operator):
bl_idname = "hello.hello"
bl_label = "Say Boom"
row = bpy.props.IntProperty()
function = bpy.props.StringProperty()
def execute(self, context):
if self.function == 'Play':
PlayPause()
print('PlayPause')
if self.function == 'Prev':
PrevTrack()
print('Last Track')
if self.function == 'Next':
NextTrack()
print('Next Track')
if self.function == 'Vup':
VolUp()
print('Volume Up')
if self.function == 'Vdown':
VdoDo()
print('Volume Down')
if self.function == 'Vmute':
Vmute()
print('Volume Down')
else:
print('Error')
return{'FINISHED'}
# ------------------------------------------------------------------------
# register and unregister functions
# ------------------------------------------------------------------------
def register():
bpy.utils.register_module(__name__)
def unregister():
bpy.utils.unregister_module(__name__)
if __name__ == "__main__":
register()
[edit] doesn’t work on mac YET