AppleScript to "funnel" MP3s to a non-Mac player

Which is to say, copy to a Mac-unfriendly MP3 player.

I’m already aware of a few “do shell script” utilizations and their syntax (POSIX path of, quoted form of, etc.) and have used them for such things as file- and folder-deletion droplets. I’m a pretty fair hand at navigating directories in Terminal and “faking” same in AppleScript. Helps I have PathSnagger CMM.

I also happen to have a very “dumb” (in terms of neither recognizing the unplayability of, nor being able to delete, AppleDouble '._" files – had to use up a trial Evaluation session in TinkerTool System to clean the silly thing out) cheap USB MP3/WMA player – happens to be the one TigerDirect sells for around $30US. I’ve adopted the habit of using Terminal to make clean “cp” copies of any MP3 or WMA files I wish to put on this thing, but I wanted to know if I could write a script, to be saved as a droplet, that would – ideally – do the following:

  1. Locate and get the name or mount-point “address” of a mounted USB disk.
  2. Copy a sound file (MP3, WMA or WAV) to that disk’s root folder
  3. Give an option (via dialog box) to eject same USB disk.

Hope it’s not too tall an order. A skeleton script that pointed me in a “right direction” is what I’m looking for.

TIA

Silversleeves
(nick comes from LONDON by Edward Rutherfurd, btw)

Model: PowerMac G4 QS 1.25 Dual MDD
AppleScript: 1.9.3
Browser: Firefox 1.5.0.8
Operating System: Mac OS X (10.3.9)

Hi,

here are two snippets to get the reference and name of the Stick and eject it with a dialog prompt
This is an example for a stick which is not Mac OS Formatted and capacity < 1GB

tell application "System Events"
	set USBStick to 1st disk whose format is not Mac OS Extended format and capacity < 1.0E+9 and local volume is true
	set USBname to name of USBStick
end tell
tell application "Finder"
	set AnswBut to button returned of (display dialog "Do you want to eject disk " & USBname & "?" buttons {"Cancel", "OK"} default button 2)
	if AnswBut is "OK" then eject disk USBname -- "if AnswBut...then" is actually not necessary because button Cancel stops the script
end tell
set D to do shell script "diskutil list" -- gets a list of everything (that the system regards as a disk) thats live and connected whether mounted or not

You should be able to see the mount point there. If it’s mounted, the first line in the identifier column will have an asterisk.

Again, on my machine, my FW hard drive shows up like this:

where the disk1s3 at the end is the drive. In my case, to mount it, if it’s been dismounted but is running, I use:

set Ext to last word of last paragraph of (do shell script "diskutil list") -- gets a list of everything thats live and connected whether mounted or not.
-- to mount it...
do shell script "diskutil mount " & Ext

Addendum: I can’t help with the rest – don’t have anything to test with.

It’s funny you should post this today. I was just about to throw my daughters new mp3 player out the window (after crushing, boiling, burning, and dismembering it, of course), when I got interested in the technical reasons why this piece of junk was behaving so poorly. I’m having the same problem with a little coby player, and once this thing is corrupted, it’s done for. The doc’s are pathetic for the device, and the manufacturer tech support was essentially “send it back and have the seller send you a new one”. I’ll look into this and see if I can find anything else. I may go so far as to write a little app for managing it’s contents, if that seems to help anything. I’ll keep your screen name and this thread on record, and let you know what tricks I find or method I end up with to make it work.

Good luck, and please let me know if you find any more pearls of wisdom regarding these little buggers. They sure have potential, if you can get them to do what the box says they can do. :rolleyes:

j

Now that I’ve thought about it a bit, this idea has wider potential than simply providing a means to copy audio files to unfriendly MP3 players. At the base of it is a means to, when used with files that are amenable to this (archives, disk images, graphic images sans legacy-style resource forks), for copying such files to just about any thumb drive not formatted Mac, cleanly – which is to say, unaccompanied by files only the OS X Finder can make any use of – and efficiently (the latter assuming all the files one would copy belong to “everybody” on that system, so far as permissions go).

Maybe it’s putting the cart before the horse, as the second and third “ideal” functions of such a droplet are yet to be puzzled out fully, but I suppose a good name for this droplet might be either “MP3Funnel” or “StickDepot” (the latter evoking the image of a train depot or intercity bus station).

Some arbitrary thoughts to peruse and forget in an hour.

Silversleeves

After a few days away from it, I’m looking at it again.

I’ve decided to approach this by naming the MP3 player stick specifically.

Here’s my latest script:

on open the_Item
	set thingJ to the_Item
	set nameJ to the name of (info for the_Item)
	set unixJ to POSIX path of thingJ
	set linuxJ to quoted form of unixJ
	set gnunameJ to nameJ
	set tripOut to (" /Volumes/CHI_POD/" & gnunameJ) as string
	set copyQry to (display dialog "Copy " & (gnunameJ) & " to disk CHI_POD?" buttons {"yes", "no"})
	set gink to button returned of copyQry
	if gink = "yes" then
		set the_Copy to (do shell script "cp " & linuxJ & tripOut)
	else
		quit
	end if
end open

It seems to work OK until it gets to the actual task of copying, then it gives an error that looks very Terminal/Unix in context. As it has to run as a droplet, I’m not sure I could grab the specific text of the error to paste here. Anyone have any ideas as to what I could be doing wrong?

Silversleeves

Hi,

I would also escape the destination path like this

set tripOut to space & quoted form of ("/Volumes/CHI_POD/" & gnunameJ)

I’m not sure whether the UNIX data separator (space) is handled properly in quotes, so I wrote it separately

Hey, NedBroy1968.

I’ve been messing with this a bit the past couple days, and here’s what I came up with. My preferred method of dealing with my cheap little player is to go into my itunes library and drag my music right from itunes to the disk on the desktop. This makes it really easy to manage it’s songs, and I can listen to them and get info about them before I drag them over to the player. I spent a little bit of time trying to make a small app that would act as an intermediary, where I could deposit files, then use the ‘cp’ command to transfer files over using unix. While that does have it’s advantages, it’s a lot more work than I have time for right now. What I’m doing for now is using itunes to drag&drop all my files to the player. Then use this little droplet (save it as an application) to use the unix ‘rm’ command to remove all of the hidden “._” files from the drive before ejecting it. Works good, and handles the stripping of any unwanted files all at once.

on open droppedPath
	set droppedName to (name of (info for droppedPath)) as string
	set droppedPath to (POSIX path of (item 1 of droppedPath)) as string
	
	set bootVolume to (boot volume of (system info)) as string
	set mountedVolumes to (list disks)
	
	if ((droppedName is not bootVolume) and (mountedVolumes contains droppedName)) then
		try
			set script_rm to ("cd '" & droppedPath & "'; rm -r ._*") as string
			do shell script script_rm
			--on error errmsg --> Uncomment if you want to see any errors (see notes in post)
			--display dialog errmsg
		end try
	else
		display dialog "Not a Valid Volume!" buttons {"OK"} default button "OK"
	end if
end open

It checks to make sure that you’re not dropping the hard drive on it and that it’s name matches one of the currently mounted volumes. I’ve commented out the error-handling for the actual unix command block that deletes the files, because it also throws an error if no files were found to delete. The way it’s posted above, it just runs, and if nothing was found it ignores the error.

If I get to making an app to manage the drive’s contents, I’ll let you know. If you do a search for delete “._” files mp3 you’ll find a handful of posts one the web that discuss this very topic.

Good luck,
j

Took another look, added a few lines and came up with this working script (woks as an applet).

on open the_Item
	set thingJ to the_Item
	set nameJ to the name of (info for the_Item)
	set unixJ to POSIX path of thingJ
	set linuxJ to quoted form of unixJ
	set gnunameJ to nameJ
	set tripOut to space & quoted form of ("/Volumes/CHI_POD/" & gnunameJ)
	set copyQry to (display dialog "Copy " & (gnunameJ) & " to disk CHI_POD?" buttons {"yes", "no"})
	set gink to button returned of copyQry
	if gink = "yes" then
		set the_Copy to (do shell script "cp " & linuxJ & tripOut)
		display dialog "Copied with no errors."
	else
		quit
	end if
end open

Now to “flex it out” a bit, ie, make it useful for more than one MP3 stick, how would I integrate, for instance, StefanK’s code from the 23rd (which persists in an applet of mine I called “StickEjector”), shown here …

tell application "System Events"
	set USBStick to 1st disk whose format is not Mac OS Extended format and capacity < 1.0E+9 and local volume is true
	set USBname to name of USBStick
end tell

tell application "Finder"
	set AnswBut to button returned of (display dialog "Do you want to eject disk " & USBname & "?" buttons {"Cancel", "OK"} default button 2)
	if AnswBut is "OK" then eject disk USBname -- "if AnswBut...then" is actually not necessary because button Cancel stops the script
end tell

… with what I got to work of the “drop-copier”? As I wrote here on the 24th, this has potential to do more than copy MP3s to non-Mac players cleanly, so I’d like to give it that potential asap. But even for the original purpose, integrating one script with the other works, because not everybody is going to want to, nor necessarily know how to, edit in the name of their own USB thumb drives just so the script works as well for them as it did for me.

SO while I’m waiting on advice, I’ll try and apply my so-far-unimaginative solutions to the problem. Thanks to all who have contributed advice and code to making this a success so far.

Silversleeves.

Stefan,

How did you get the “1.0E+9” in your code? Is there a way in AppleScript (or OS X’s Calculator) to get values like that?

Silversleeves

just type 1000000000 in Script Editor and compile !
this is AppleScript’s “behavior” to handle large numbers

A new idea struck me yesterday.

How about making this script copy more than one file?

I suppose I could work in a repeat loop, similar to the ones in my multiple-file deletion droplets. But I’m not sure where to put one in so it would work with the code I’ve put together so far. I know the other thing I’d want to change would be the “position” of the dialog that said “Copied with no errors.” At the same time I was thinking of modifying that, so it would say (some number of files) were “Copied with no errors.” So the repeat loop would have to have a counter, and it’s been years since I’ve gotten one of those to work (Mac owner since 1993; first – and last till now – exposure to AppleScript in 1996-97).

So how would I insinuate such a loop into the working “copier” droplet I posted earlier? To give you all something to look at, here’s the code from another working droplet (made also with the help of folks on this forum) that performs a task on multiple files. At one stage it had a counter, but the variable data went nowhere useful, so at the advice of others it was eliminated.

on open the_Items
	repeat with an_item in the_Items
		set scrood to POSIX path of an_item
		set scrood_double to (quoted form of scrood)
		set theText01 to (do shell script "rm -fP " & scrood_double & "")
	end repeat
end open

I’ll try one or two things on my own while waiting for advice.

Silversleeves

Your sample Code does the job.
A counter is not necessary because the repeat with x in y uses an internal counter.
Its the same like:

on open the_Items
	repeat with an_item from 1 to count the_Items
		set scrood_double to quoted form of POSIX path of item an_item of the_Items
		set theText01 to (do shell script "rm -fP " & scrood_double & "")
	end repeat
end open

Getting an error with the modified code.

Backtracking a bit: I had the single-file copier spot an audio CD and try to copy to it. Before then, the code to specify for System Events what the maximum capacity should be didn’t seem so important. Putting it back in was just another modification I made.

Run as a droplet, the script below, even before the first dialog displays, gives the error

So here it is.


on open the_Items
	
	tell application "System Events"
		set USBStick to 1st disk whose format is not Mac OS Extended format and capacity is less than 1.073741824E+9 and local volume is true
		set USBname to name of USBStick
	end tell
	
	set g to (number of items) in the_Items
	repeat with i in g
		set thingJ to i as alias
		set nameJ to the name of (info for i)
		set unixJ to POSIX path of i
		set linuxJ to quoted form of unixJ
		set gnunameJ to nameJ
		set tripOut to space & quoted form of ("/Volumes/" & USBname & "/" & gnunameJ)
		set copyQry to (display dialog "Copy " & (g) & " items to disk " & USBname & "?" buttons {"Yes", "No"} default button "Yes")
		set gink to button returned of copyQry
		if gink = "yes" then
			set the_Copy to (do shell script "cp " & linuxJ & tripOut)
		end if
	end repeat
	
	display dialog g & "items copied with no errors."
	tell application "Finder"
		set AnswBut to button returned of (display dialog "Do you want to eject disk " & USBname & "?" buttons {"Cancel", "OK"} default button "OK")
		if AnswBut is "OK" then eject disk USBname -- "if AnswBut...then" is actually not necessary because button Cancel stops the script
	end tell
	
end open

Where could I be going wrong )or leavng something out or putting too much in at an odd angle)?

Silversleeves

this can’t work:

set g to (number of items) in the_Items

number of items is the count not the items themselves
or easier:

set g to count the_Items

change this line:

repeat with i in the_Items

Stefan,

Re this way of entering large numbers – I think I just had an “oops”.

I used my StickEjector applet, and kept getting the error “The variable USBStick is not defined.” Turns out, now System Events seems to want a more accurate “ceiling” number (like the one I used in the draft script above – found by multiplying 1024 3 times in Calculator.app). So I c&p’d the one from that draft script into StickEjector and now it works OK. Also for some reason “<” didn’t compile to the alpha “is less than” – i wound up pasting that in also.

More to the present effort (making a batch file copier out of a single file copier), I took your suggestion and also moved the “Copy” so many items "to disk " some disk “?” dialog to just before the repeat loop (to keep it from, if this is not too obvious, repeating). I also wrapped the whole loop in an if/else/endif conditional routine, so now what I have is this:

on open the_Items
	
	tell application "System Events"
		set USBStick to 1st disk whose format is not Mac OS Extended format and capacity is less than 1.073741824E+9 and local     volume is true
		set USBname to name of USBStick
	end tell
	
	set g to count the_Items
	set copyQry to (display dialog "Copy " & (g) & " items to disk " & USBname & "?" buttons {"Yes", "No"} default button 1)
	set gink to button returned of copyQry
	if gink = "Yes" then
		repeat with i in the_Items
			set thingJ to i as alias
			set nameJ to the name of (info for i)
			set unixJ to POSIX path of i
			set linuxJ to quoted form of unixJ
			set gnunameJ to nameJ
			set tripOut to space & quoted form of ("/Volumes/" & USBname & "/" & gnunameJ)
			set the_Copy to (do shell script "cp " & linuxJ & tripOut)
		end repeat
	else
		quit
	end if
	display dialog g & "items copied with no errors."
	
	tell application "Finder"
		set AnswBut to button returned of (display dialog "Do you want to eject disk " & USBname & "?" buttons {"Cancel", "OK"} default button 2)
		if AnswBut is "OK" then eject disk USBname -- "if AnswBut...then" is actually not necessary because button Cancel stops the script
	end tell
	
end open

I think I’m only a wee bit further along, frankly. Time and testing will tell. Can you see any part of this that might catch me up?

Silversleeves

Well, time and testing did reveal where I would be caught up.
I didn’t coerce g and got the error “Can’t make 2 ; ‘items copied without errors’ into a string”.

So with this tiny correction

set TheFullCount to g as string
	display dialog TheFullCount & " items copied with no errors."

… it worked.

Many many many thanks to all the forum members who helped me get this far.

My next idea for a script is one that will copy AIFs off of audio disks and make them into MP3s via lame in Terminal.1

Silversleeves

  1. Nix on that – I’ve upgraded my LAME in /usr/sbin and decided to do all my encoding from Terminal or LameBrain from now on.
    The script to parse the “.current” files in Darwin/QuickTime Streaming Server is my current pursuit.

Not quite ready to put this topic to bed.

Can anyone suggest a way of getting System Events to ignore audio (and other non-HFS+) CDs in the part of the script that deals with locating a disk to which to copy the file(s) dropped on the droplet? Does “capacity is less than” (one gig expressed exponentially) in the tell routine handle it, or is there another condition I could set that S-E would understand?

Silversleeves

you can additionally write

...and format is not audio format

I did that for another “draft” applet. I also put in “…and format is not ISO 9660 format” in case the disc in the opitcal drive of the user’s Mac happened to be in that format. However, there’s a collision of logic, so to speak, with a “not ISO” condition, because any optical disk that didn’t have a less-than-1GB capacity (excepting maybe Sony’s 1.3Gb CD-R’s) would be a DVD and thus not in ISO but UDF format. and the “less than 1Gb” condition takes care of those to begin with. This showed up when I tested the draft applet with both a DOS/FAT stick and a Joliet disk (identified in the Finder as ISO 9660) mounted.

I looked at the System Events scripting dictionary again, and saw one of the elements of class disk was free space. Well, I thought I’d make use of that, because in most instances burned or mass-produced CDs and DVDs only mount if one or more “threads” are closed, leaving a zero-byte capacity. Computers 101 really. So I insinuated the condition “and free space is greater than 0.0” (saying as the element description called for a double integer) in the set USBStick to variable definition “paragraph” (it’s starting to look like the start of a book G), compiled, saved and ran it with the same two disks mounted as in my previous test. The dialog box that came up showed the name of the stick, instead of the name of the CD, as previous saves of the same applet were wont to do. And it worked.

Silversleeves