Welcome, guest | Sign In | My Account | Store | Cart
#======================================================================
# 
# winamp.py - winamp control interface
# copyright 2006 (c) skywind3000@hotmail.com
#
# NOTE: 
#
# This module is a tiny winamp implementation using ctypes, which
# presents mp3/wav/mid/ogg... playback in python by calling winamp
# plugins. Treating it as a little example for advanced ctypes usage
#
# most of common plugins in winamp5 or above need a shared dll named 
# nscrt.dll, you need copy it to current dir from %winamp%/plugins/
#
# the plugins in winamp4.0/2.0 do not need it, you can only copy 
# in_*.dll or out_*.dll to current dir 
#
# for more information, please see http://www.winamp.com/nsdn/winamp/
# to get full example (in_mp3.dll, out_wave.dll, sample.mp3 include): 
# http://www.joynb.net/blog/up/1166948100.rar
#
#======================================================================

import sys, os, time
import ctypes
from ctypes import c_long, c_char_p, c_voidp, c_int, c_short, c_byte
from ctypes import POINTER, CFUNCTYPE, pointer, byref
from ctypes import cast, addressof, cdll, windll
from ctypes.wintypes import *


#----------------------------------------------------------------------
# struct OutModule definition
#----------------------------------------------------------------------
class OutModule(ctypes.Structure):
    _fields_ = [
		("version", c_long), 
		("description", c_char_p),
		("id", c_int),
		("hMainWindow", c_voidp),
		("hDllInstance", c_voidp),
		("config", CFUNCTYPE(None, c_voidp)),
		("about", CFUNCTYPE(None, c_voidp)),
		("init", CFUNCTYPE(None,)),
		("quit", CFUNCTYPE(None,)),
		("open", CFUNCTYPE(c_int, c_int, c_int, c_int, c_int, c_int)),
		("close", CFUNCTYPE(None,)),
		("write", CFUNCTYPE(c_int, c_voidp, c_int)),
		("canwrite", CFUNCTYPE(c_int,)),
		("isplaying", CFUNCTYPE(c_int,)),
		("pause", CFUNCTYPE(c_int, c_int)),
		("setvol", CFUNCTYPE(None, c_int)),
		("setpan", CFUNCTYPE(None, c_int)),
		("flush", CFUNCTYPE(None, c_int)),
		("getoutputtime", CFUNCTYPE(c_int,)),
		("getwrittentime", CFUNCTYPE(c_int,))
	]


#----------------------------------------------------------------------
# struct InModule definition
#----------------------------------------------------------------------
class InModule(ctypes.Structure):
    _fields_ = [
		("version", c_long), 
		("description", c_char_p),
		("hMainWindow", c_voidp),
		("hDllInstance", c_long),
		("FileExtensions", c_char_p),
		("is_seekable", c_int),
		("UsesOutputPlug", c_int),
		("config", CFUNCTYPE(None, c_voidp)),	# 7
		("about", CFUNCTYPE(None, c_voidp)),
		("init", CFUNCTYPE(None,)),
		("quit", CFUNCTYPE(None,)),
		("getfileinfo", CFUNCTYPE(None, c_char_p, c_char_p, POINTER(c_int))),
		("infobox", CFUNCTYPE(c_int, c_char_p, c_voidp)),
		("isourfile", CFUNCTYPE(c_int, c_char_p)),
		("play", CFUNCTYPE(c_int, c_char_p)), # 14
		("pause", CFUNCTYPE(None, )),
		("unpause", CFUNCTYPE(None, )),
		("ispaused", CFUNCTYPE(c_int, )),
		("stop", CFUNCTYPE(None, )),
		("getlength", CFUNCTYPE(c_int, )),
		("getoutputtime", CFUNCTYPE(c_int, )),
		("setoutputtime", CFUNCTYPE(None, c_int)),
		("setvol", CFUNCTYPE(None, c_int)),
		("setpan", CFUNCTYPE(None, c_int)), # 23
		("SAVSAInit", CFUNCTYPE(None, c_int, c_int)),
		("SAVSADeInit", CFUNCTYPE(None, )),
		("SAAddPCMData", CFUNCTYPE(None, c_voidp, c_int, c_int, c_int)),
		("SAGetMode", CFUNCTYPE(c_int,)),
		("SAAdd", CFUNCTYPE(None, c_voidp, c_int, c_int)),
		("VSAAddPCMData", CFUNCTYPE(None, c_voidp, c_int, c_int, c_int)),
		("VSAGetMode", CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))),
		("VSAAdd", CFUNCTYPE(None, c_voidp, c_int)),
		("VSASetInfo", CFUNCTYPE(None, c_int, c_int)),
		("dsp_isactive", CFUNCTYPE(c_int, )),
		("dsp_dosamples", CFUNCTYPE(c_int, c_voidp, c_int, c_int, c_int, c_int)),
		("eqset", CFUNCTYPE(None, c_int, c_char_p, c_int)),
		("setinfo", CFUNCTYPE(None, c_int, c_int, c_int, c_int)),
		("outmod", POINTER(OutModule))
	]


# export OutModule from dll
def load_outmod(dllname):
	outdll = ctypes.cdll.LoadLibrary(dllname)
	getaddr = outdll.winampGetOutModule
	getaddr.restype = c_voidp
	# outmod = (OutModule*)(getaddr())
	outmod = cast(getaddr(), POINTER(OutModule))[0]
	return outmod

# export InModule from dll
def load_inmod(dllname):
	indll = ctypes.cdll.LoadLibrary(dllname)
	getaddr = indll.winampGetInModule2
	getaddr.restype = c_voidp
	# inmod = (InModule*)(getaddr())
	inmod = cast(getaddr(), POINTER(InModule))[0]
	return inmod

# init inmod/outmod together
def init_modules(inmod, outmod):
	def _SAVSAInit(n1, n2): pass
	def _SAVSADeInit(): pass
	def _SAAddPCMData(n1, n2, n3, n4): pass
	def _SAGetMode(): return 0;
	def _SAAdd(n1, n2, n3): pass
	def _VSAAdd(n1, n2): pass
	def _VSAAddPCMData(n1, n2, n3, n4): pass
	def _VSAGetMode(n1, n2): return 0
	def _VSASetInfo(n1, n2): pass
	def _dspisactive(): return 0
	def _dspyesactive(): return 1
	def _dspdo(n1, n2, n3, n4, n5): return 0
	def _setinfo(n1, n2, n3, n4): pass
	def _eqset(n1, n2, n3): pass

	# setting up default dummy functions
	inmod.SAVSAInit = CFUNCTYPE(None, c_int, c_int)(_SAVSAInit)
	inmod.SAVSADeInit = CFUNCTYPE(None, )(_SAVSADeInit)
	inmod.SAAddPCMData = CFUNCTYPE(None, c_voidp, c_int, c_int, c_int)(_SAAddPCMData)
	inmod.SAGetMode = CFUNCTYPE(c_int,)(_SAGetMode)
	inmod.SAAdd = CFUNCTYPE(None, c_voidp, c_int, c_int)(_SAAdd)
	inmod.VSAAdd = CFUNCTYPE(None, c_voidp, c_int)(_VSAAdd)
	inmod.VSAAddPCMData = CFUNCTYPE(None, c_voidp, c_int, c_int, c_int)(_VSAAddPCMData)
	inmod.VSAGetMode = CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))(_VSAGetMode)
	inmod.VSASetInfo = CFUNCTYPE(None, c_int, c_int)(_VSASetInfo)
	inmod.dsp_isactive = CFUNCTYPE(c_int, )(_dspisactive)
	inmod.dsp_dosamples = CFUNCTYPE(c_int, c_voidp, c_int, c_int, c_int, c_int)(_dspdo)
	inmod.setinfo = CFUNCTYPE(None, c_int, c_int, c_int, c_int)(_setinfo)
	inmod.eqset = CFUNCTYPE(None, c_int, c_char_p, c_int)(_eqset)

	# setting up other members
	inmod.outmod = pointer(outmod)
	GetActiveWindow = windll.user32.GetActiveWindow
	inmod.hMainWindow = GetActiveWindow()
	inmod.hDllInstance = 0
	outmod.hMainWindow = GetActiveWindow()
	outmod.hDllInstance = 0

	return  0	


#----------------------------------------------------------------------
# Global Variables
#----------------------------------------------------------------------
__in_module = None
__out_module = None

#----------------------------------------------------------------------
# Winamp Main Interface
#----------------------------------------------------------------------
def init(indll, outdll):
	global __in_module, __out_module
	quit()
	try:
		__in_module	= load_inmod(indll)
		__out_module = load_outmod(outdll)
	except: return -1
	init_modules(__in_module, __out_module)
	__out_module.init()
	__in_module.init()
	return 0

def quit():
	global __in_module, __out_module
	if __in_module: 
		__in_module.stop()
		__in_module.quit()
	if __out_module: __out_module.quit()
	__in_module = None
	__out_module = None

def play(name):
	return __in_module.play(name)

def stop():
	__in_module.stop()

def pause(status = True):
	if status: __in_module.pause()
	else: __in_module.unpause()

def ispaused():
	return __in_module.ispaused()

def getlength():
	return __in_module.getlength()

def gettime():
	return __in_module.getoutputtime()

def settime(timems):
	__in_module.setoutputtime(timems)

def setvol(vol = 1.0):
	__in_module.setvolume(int(vol * 255))

def setpan(pan = 0.0):
	__in_module.setpan(int(pan * 127))

def fileinfo(name):
	i = ctypes.c_int()
	s = ctypes.create_string_buffer('\000' * 256)
	__in_module.getfileinfo(name, s, pointer(i))
	return (s.value, i.value)


#----------------------------------------------------------------------
# Testing Code
#----------------------------------------------------------------------
if __name__ == '__main__':
	indll = 'in_mp3.dll'
	outdll = 'out_wave.dll'
	if init(indll, outdll):
		print 'cannot load plugins'
		sys.exit(0)
	name = 'sample.mp3'
	info = fileinfo(name)

	def ms2time(ms):
		if ms <= 0: return '00:00:000'
		time_sec, ms = ms / 1000, ms % 1000
		time_min, time_sec = time_sec / 60, time_sec % 60
		time_hor, time_min = time_min / 60, time_min % 60
		if time_hor == 0: return '%02d:%02d:%03d'%(time_min, time_sec, ms)
		return '%02d:%02d:%02d:%03d'%(time_hor, time_min, time_sec, ms)

	print 'Playing "%s" (%s), press \'q\' to exit ....'%(info[0], name)
	play(name)
	user32 = ctypes.windll.user32
	while 1:
		user32.GetAsyncKeyState.restype = WORD
		user32.GetAsyncKeyState.argtypes = [ ctypes.c_char ]
		if user32.GetAsyncKeyState('Q'): break
		time.sleep(0.1)
		print '[%s / %s]\r'%(ms2time(gettime()), ms2time(getlength())),
		if (gettime() > 0) and (gettime() > getlength() - 3000):
			settime(0)
	print '\nstopped'
	quit()

History

  • revision 2 (17 years ago)
  • previous revisions are not available