New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add before_item_moved event #742

Merged
merged 1 commit into from May 2, 2014

Conversation

Projects
None yet
2 participants
@rspeicher
Contributor

rspeicher commented May 2, 2014

This event gets called just before util.move with the same arguments as the item_moved event.

This might seem useless, but I had a specific use case for it. I still use iTunes to organize and play my music (I know, I know), but beets' organization and renaming really appeals to me, so I wanted to start moving towards that. Problem is, when beets moves a file on the filesystem iTunes picks up the change but then immediately forgets it as soon as the app closes. The next time you play the file it says it can't find it.

I've found the only way to get around this is to tell iTunes, through Applescript, to set the new location for the file after it's moved. I wrote a beetsplugin to do this on each item_moved event, but the problem is Applescript provides no good way to look up a file by its path. The only reliable way to find a track by its path is to "add" the file to iTunes. If the file already exists, iTunes returns a reference to the track which we can then update.

Still following? You can't add a file to iTunes that doesn't exist, even a file it already has in its library, so by the time we get to item_moved it's already too late. I needed before_item_moved so I can add the file in its old location, store its reference, and then after it's moved tell iTunes its new location.

If anyone's interested, this is the plugin I came up with:

import logging
import appscript
from beets.plugins import BeetsPlugin

# Global logger.
log = logging.getLogger('beets')

# Global variable to store the iTunes track reference of a file before it's moved
track_ref = None

class ItunesMover(BeetsPlugin):
    pass

def hfspath(posix):
    return appscript.mactypes.File(posix).hfspath

@ItunesMover.listen('before_item_moved')
def before_move(item, source, destination):
    global track_ref

    # Convert the POSIX path to an HFS one
    source_hfs = hfspath(source)

    # iTunes fuckery:
    #
    # We tell iTunes to add the file. Hopefully it's already in iTunes, in
    # which case iTunes just returns the track reference. This is the only way
    # to look up a file by its path without looping through a bunch of tracks.
    track_ref = appscript.app("iTunes").add(source_hfs)

@ItunesMover.listen('item_moved')
def moved(item, source, destination):
    global track_ref

    try:
        track_ref.location.set(hfspath(destination))
        track_ref = None
    except appscript.CommandError:
        log.debug(u"Could not set iTunes location to %s (probably doesn't exist)" % destination)
Add before_item_moved event
This event gets called just before `util.move` with the same arguments
as the `item_moved` event.

sampsyo added a commit that referenced this pull request May 2, 2014

@sampsyo sampsyo merged commit 27804ce into beetbox:master May 2, 2014

1 check passed

continuous-integration/travis-ci The Travis CI build passed
Details

sampsyo added a commit that referenced this pull request May 2, 2014

@sampsyo

This comment has been minimized.

Show comment
Hide comment
@sampsyo

sampsyo May 2, 2014

Member

Merged; thanks!

I'm really impressed at what a slick solution you came up with here. Integration with iTunes is something that comes up fairly often—it is nice to have iTunes see when things move around in beets—and we haven't had a great solution.

Would you be interested in publishing this plugin or including it in beets? The degenerating state of appscript has me a little worried, but that aside, this seems about ready to include as a standard plugin.

Member

sampsyo commented May 2, 2014

Merged; thanks!

I'm really impressed at what a slick solution you came up with here. Integration with iTunes is something that comes up fairly often—it is nice to have iTunes see when things move around in beets—and we haven't had a great solution.

Would you be interested in publishing this plugin or including it in beets? The degenerating state of appscript has me a little worried, but that aside, this seems about ready to include as a standard plugin.

@rspeicher

This comment has been minimized.

Show comment
Hide comment
@rspeicher

rspeicher May 2, 2014

Contributor

If you think other people would find it useful, by all means, feel free to add it. Could probably use some cleanup though.

Yeah, I have the same concerns you do with appscript, but the alternative is running commands through osascript and parsing the output, which I couldn't find an elegant solution for. My Python's still pretty weak, though, so maybe there's a better way.

Any ideas about some safeguard for dealing with files that aren't in iTunes? Maybe in the item_moved handler you could check the track reference's date_added (I think that's the property) value and if it's in the last minute, delete it?

Contributor

rspeicher commented May 2, 2014

If you think other people would find it useful, by all means, feel free to add it. Could probably use some cleanup though.

Yeah, I have the same concerns you do with appscript, but the alternative is running commands through osascript and parsing the output, which I couldn't find an elegant solution for. My Python's still pretty weak, though, so maybe there's a better way.

Any ideas about some safeguard for dealing with files that aren't in iTunes? Maybe in the item_moved handler you could check the track reference's date_added (I think that's the property) value and if it's in the last minute, delete it?

@sampsyo

This comment has been minimized.

Show comment
Hide comment
@sampsyo

sampsyo May 2, 2014

Member

Okay; I'll put this on hold for now, but if one of us (or an interested third party) has some extra time, a PR with docs and such will be quickly merged.

Member

sampsyo commented May 2, 2014

Okay; I'll put this on hold for now, but if one of us (or an interested third party) has some extra time, a PR with docs and such will be quickly merged.

@rspeicher rspeicher deleted the rspeicher:rs-before_item_moved-event branch May 2, 2014

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment