auto identification of connected printer (Mac)
Peter Brigham MD
pmbrig at gmail.com
Thu Oct 28 12:21:46 EDT 2010
In case anyone else would find it useful, I've finally managed to tune
up my handlers for LiveCode printing from a Mac laptop, designed to
avoid any unnecessary printing dialogs. This is useful if you, like
me, use a LiveCode app on your laptop in a number of different venues
and need to print using the currently connected printer. I got annoyed
that every time I switched venues I had to tell the system what
printer to use (I do a lot of printing of patient notes,
prescriptions, etc.). The system knows what's connected, right? So if
I have one and only one printer connected why should it have to ask me
to choose my printer?
The set of handlers below will detect the currently available printer,
whether connected by USB or on a wireless network, and automatically
send the print job to that printer (if I'm printing from a LiveCode
script).
The way it works is this -- the IO registry is queried with a shell
call and the result is parsed to identify USB-connected printers (not
a foolproof algorithm, but seems to work so far). If the IOR listing
is already associated with a printer name then that printer is used,
all done. If no printer name has been associated with the IOR listing
then the user is asked to identify the printer to be used and the IOR
listing / printerName association is stored as a custom prop, so that
thereafter it will be used automatically.
If there are no USB printers identified, a shell call fetches the MAC
address of any wireless network you are connected to. If none, then
the user gets "not connected to any printer," and printing is aborted.
Otherwise, the user is asked once, as above, to identify the printer
on that network, and the MAC address / printerName association is
stored for future use.
To use, just call "checkPrinter" before any printing command in
LiveCode, and everything else is taken care of. Should work on Mac
laptops. Sorry, I don't have a Windows or Linux laptop to develop the
corresponding routines on for the other OSes, but that should be do-
able for anyone with the need.
Thanks to the dozen or more members of this list that have helped me
with ideas, shell calls, etc. I absolutely could not have done it
without you.
-- Peter
Peter M. Brigham
pmbrig at gmail.com
http://home.comcast.net/~pmbrig
-----------------
constant storageStack = "<yourStackNameHere>"
-- the short name of the stack that stores the customprops for the
printer names
on checkPrinter printingWhat
if the controlkey is down then
-- bypass the routines entirely
answer printer
exit checkPrinter
end if
-- get listing of connected printer in IO registry, and MAC
address for wireless
put getActivePrinter() into tLivePrinterInIOR
put sr(tLivePrinterInIOR) into tLivePrinterInIOR
put tLivePrinterInIOR into IORrawPrinterList
put the printername into origPrinterName
put getWirelessMACaddress() into MACaddr
if tLivePrinterInIOR = empty then
-- no USB printer detected
if MACaddr = empty then
put "You are not connected to any active printer. Please
check that" && \
"your printer is turned on and connected properly."
into cmt
answer cmt as sheet
exit to top -- abort printing
else -- connected to a network
put the MACaddrToPrinterName[MACaddr] of stack storageStack
into tLivePrinterName
if tLivePrinterName <> empty then
set the printername to tPossiblePrinterName
else
put "Please choose the wireless printer on this network"
&& \
"so it can be identified in the future." into cmt
answer cmt as sheet
set the systemprintselector to true
answer printer
-- sets the printername (used by Rev for printing)
if the result = "cancel" then exit to top
-- abort printing
put the printername into tPrinterName
set the MACaddrToPrinterName[MACaddr] of stack
storageStack to tPrinterName
-- store printer name for this device
end if
exit checkPrinter -- proceed to printing
end if
end if
-- the following is when there is a possible USB printer and no
wireless printer
-- more than one device might be a printer
-- but we might know this printer already
repeat for each line p in tLivePrinterInIOR
put the IORtoPrinterName[p] of stack "PDdata" into
tPossiblePrinterName
if tPossiblePrinterName <> empty then
-- found a known printer, set it, then done
set the printername to tPossiblePrinterName
exit checkPrinter -- proceed to printing
end if
end repeat
-- no known printers found,
-- ask user to sort it out
-- have to construct answer dialog
-- with buttons for each device
if the number of lines of tLivePrinterInIOR > 1 then
put q("cancel") into btnList
repeat for each line p in tLivePrinterInIOR
put q(truncate(p,18)) into btnName
put q(truncate(p,35)) into promptLine
put " and " & btnName after btnList
put " & cr &" && promptLine after promptList
end repeat
put "There are several USB devices currently connected. Please
identify the" \
&& "one that is the printer so it will be recognized in
the future:" \
& quote & promptList into theDo
put "answer" && quote before theDo
put " with" && btnList && "as sheet" after theDo
do theDo
put it into whichDevice
if whichDevice = "cancel" then exit to top
if char -1 of whichDevice = "…" then delete char -1 of
whichDevice
put lineoffsets(whichDevice,tLivePrinterInIOR) into pOffset
if the number of items of pOffset > 1 then
answer "Having difficulty identifying your printer. Please
unplug" \
&& "all USB devices except the active printer and try
printing again." \
as sheet
exit to top
else
put line pOffset of tLivePrinterInIOR into tLivePrinterInIOR
end if
end if
-- now tLivePrinterInIOR contains one line
put the IORtoPrinterName[tLivePrinterInIOR] of stack "PDdata" into
tLivePrinterName
-- system prefs name of currently live printer,
-- stored when printer first encountered
if origPrinterName = tLivePrinterName and origPrinterName <> empty
then
-- currently connected to the chosen printer,
-- proceed to printing
exit checkPrinter
end if
-- else:
if tLivePrinterName = empty then
-- never seen this printer
setupicons
put "Please choose the current printer (" & tLivePrinterInIOR & \
") so it can be identified in the future." into cmt
answer cmt as sheet
set the systemprintselector to true
answer printer
-- sets the printername (used by Rev for printing)
if the result = "cancel" then exit to top
-- abort printing
put the printername into tPrinterName
set the IORtoPrinterName[tLivePrinterInIOR] of stack
storageStack to tPrinterName
-- store printer name for this device
else if tCurrentRevPrinterName <> tLivePrinterName then
-- a different known printer is currently live, just tell Rev
to use it
set the printername to tLivePrinterName
end if
end checkPrinter
function getUSBdevices
-- returns list of currently connected USB devices
-- with tab-indented list of properties for each
-- get USB device info from system profiler
set the hideconsolewindows to true
put shell("system_profiler -detailLevel full SPUSBDataType") into
tData
-- convert data to one line per USB device
replace (colon & cr & cr) with numToChar(245) in tData -- device
name
replace (cr & cr) with numtoChar(250) in tData
replace cr with tab in tData
replace numtoChar(245) with (colon & tab) in tData
replace numtoChar(250) with cr in tData
replace tab with cr & tab in tData
repeat until cr & space is not in tData
replace cr & space with cr in tData
end repeat
repeat until tab & space is not in tData
replace tab & space with tab in tData
end repeat
delete word 1 of tData
return tData
end getUSBdevices
function getWirelessMACaddress
put shell("cd /usr/sbin;system_profiler SPNetworkDataType
#####REVEXCLUDEDSTRING#####grep -i signature") into s
set the itemdel to "="
put line 1 of (item -1 of s) into tMAC
return tMAC
end getWirelessMACaddress
function getActivePrinter
set the hideconsolewindows to true
put shell("ioreg") into tList
filter tList with "*<class IOUSBDevice*"
filter tList without "*UserClient*"
filter tList without "*Keyboard*"
filter tList without "* IR *"
filter tList without "*Wireless*"
filter tList without "*mouse*"
filter tList without "*iSight*"
filter tList without "*Store 'n' Go*"
filter tList without "*iPhone*"
-- more filtering needed for other devices?
filter tList without empty
repeat for each line d in tList
-- could be more than one
put offset("+-o",d)+4 into startChar
put offset("@",d)-1 into endChar
put (char startChar to endChar of d) & cr after printerList
end repeat
delete char -1 of printerList
return printerList
end getActivePrinter
function sr str
-- strips white space fore and aft
return word 1 to -1 of str
end sr
function q str
return quote & str & quote
end q
function truncate str, n
-- returns a string of at most n chars
if length(str) <= n then return str
return char 1 to n-1 of str & "…" -- ellipsis
end truncate
function offsets str,ctr
-- returns a comma-delimited list of all the offsets of str in ctr
put "" into mosList
put 0 into startPoint
repeat
put offset(str,ctr,startPoint) into os
if os = 0 then exit repeat
add os to startPoint
put startPoint & "," after mosList
end repeat
if char -1 of mosList = "," then delete last char of mosList
if mosList = "" then return "0"
return mosList
end offsets
function lineOffsets str,ctr
-- returns a comma-delimited list of all the lineoffsets of str in
ctr
put offsets(str,ctr) into charList
if charList = "0" then return "0"
put the number of items of charList into nbr
put "" into mlo
repeat for each item n in charList
put the number of lines of (char 1 to n of ctr) & "," after mlo
end repeat
if char -1 of mlo = "," then delete char -1 of mlo
return mlo
end lineOffsets
More information about the use-livecode
mailing list