Beispiel #1
0
 def append_song(self, song):
     """
     Append song `song` to the playlist.
     """
     ps = PlaylistSong(playlist=self, song=song)
     self.playlist_songs.append(ps)
     session.flush()
Beispiel #2
0
 def delete_song(self, position):
     """
     Delete the song at position `position`.
     """
     ps = self.playlist_songs.pop(position)
     session.delete(ps)
     session.flush()
Beispiel #3
0
 def insert_song(self, position, song):
     """
     Insert song `song` at position `position`
     """
     ps = PlaylistSong(playlist=self, song=song)
     self.playlist_songs.insert(position, ps)
     session.flush()
Beispiel #4
0
 def insert_song(self, position, song):
     """
     Insert song `song` at position `position`
     """
     ps = PlaylistSong(playlist=self, song=song)
     self.playlist_songs.insert(position, ps)
     session.flush()
Beispiel #5
0
 def append_song(self, song):
     """
     Append song `song` to the playlist.
     """
     ps = PlaylistSong(playlist=self, song=song)
     self.playlist_songs.append(ps)
     session.flush()
Beispiel #6
0
 def delete_segment(self, position):
     """
     Delete the segment at position `position`.
     """
     seg = self.segments.pop(position)
     session.delete(seg)
     session.flush()
 def insert_segment(self, position, pace, length):
     """
     Insert a segment with pace `pace` and length `length` at position
     `position`.
     """
     self.segments.insert(position, Segment(pace=pace, length=length))
     session.flush()
 def delete_segment(self, position):
     """
     Delete the segment at position `position`.
     """
     seg = self.segments.pop(position)
     session.delete(seg)
     session.flush()
Beispiel #9
0
 def delete_song(self, position):
     """
     Delete the song at position `position`.
     """
     ps = self.playlist_songs.pop(position)
     session.delete(ps)
     session.flush()
Beispiel #10
0
 def insert_segment(self, position, pace, length):
     """
     Insert a segment with pace `pace` and length `length` at position
     `position`.
     """
     self.segments.insert(position, Segment(pace=pace, length=length))
     session.flush()
Beispiel #11
0
    def update_segment(self, position, pace=None, length=None):
        """
        Update the segment at position `position` with pace `pace` and/or
        length `length`.
        """
        if not (pace or length):
            # noop
            return

        segment = self.segments[position]
        segment.pace = pace or segment.pace
        segment.length = length or segment.length
        self.segments[position] = segment
        session.flush()
    def update_segment(self, position, pace=None, length=None):
        """
        Update the segment at position `position` with pace `pace` and/or
        length `length`.
        """
        if not (pace or length):
            # noop
            return

        segment = self.segments[position]
        segment.pace = pace or segment.pace
        segment.length = length or segment.length
        self.segments[position] = segment
        session.flush()
def playlist_example():
    slow, steady, fast, sprint = Pace(speed='Slow'), Pace(speed='Steady'), \
        Pace(speed='Fast'), Pace(speed='Sprint')

    # Create an activity plan
    plan = ActivityPlan(name='test')
    session.add(plan)
    session.flush()

    # Add 4 segments to the plan
    plan.append_segment(pace=steady, length=60)
    plan.append_segment(pace=steady, length=60)
    plan.append_segment(pace=slow, length=10)
    plan.append_segment(pace=sprint, length=60)

    # Create a playlist
    playlist = Playlist(name='test')
    session.add(playlist)
    session.flush()

    playlist.generate(plan)
def playlist_example():
    slow, steady, fast, sprint = Pace(speed='Slow'), Pace(speed='Steady'), \
        Pace(speed='Fast'), Pace(speed='Sprint')

    # Create an activity plan
    plan = ActivityPlan(name='test')
    session.add(plan)
    session.flush()

    # Add 4 segments to the plan
    plan.append_segment(pace=steady, length=60)
    plan.append_segment(pace=steady, length=60)
    plan.append_segment(pace=slow, length=10)
    plan.append_segment(pace=sprint, length=60)

    # Create a playlist
    playlist = Playlist(name='test')
    session.add(playlist)
    session.flush()

    playlist.generate(plan)
def music_example():
    # Create artists
    kanye = Artist(name='Kanye West')
    mozart = Artist(name='Wolfgang Amadeus Mozart')

    # Add artists to the DB session and flush to generate their primary key IDs
    session.add(kanye)
    session.add(mozart)
    session.flush()

    # Create songs
    stronger = Song(
        filename='stronger.mp3',
        title='Stronger',
        date_added=datetime.utcnow(),
        artist=kanye,  # Assign the artist object directly
    )
    love_lockdown = Song(
        filename='love_lockdown.mp3',
        title='Love Lockdown',
        date_added=datetime.utcnow(),
        artist=kanye,
    )

    requiem = Song(
        filename='requiem.mp3',
        title='Requiem',
        date_added=datetime.utcnow(),
        artist=mozart,
    )

    # Add songs to the DB session and flush to generate their primary key IDs
    # as well as populating the artist_id field
    session.add(stronger)
    session.add(love_lockdown)
    session.add(requiem)
    session.flush()

    # Create a playlist
    playlist = Playlist(name='test')
    session.add(playlist)
    session.flush()

    # Add some songs to the playlist
    playlist.append_song(stronger)
    playlist.append_song(love_lockdown)
    playlist.append_song(requiem)

    # Delete a song from the playlist
    playlist.delete_song(1)

    # Insert a song at number 3 in the playlist
    playlist.insert_song(2, love_lockdown)

    session.commit()

    print "Artists: %s, %s" % (kanye, mozart)
    print "Each artist's songs: Kanye: %s, Mozart: %s" % (kanye.songs,
                                                          mozart.songs)
    print "Playlist songs: %s" % playlist.songs
def music_example():
    # Create artists
    kanye = Artist(name='Kanye West')
    mozart = Artist(name='Wolfgang Amadeus Mozart')

    # Add artists to the DB session and flush to generate their primary key IDs
    session.add(kanye)
    session.add(mozart)
    session.flush()

    # Create songs
    stronger = Song(
        filename='stronger.mp3',
        title='Stronger',
        date_added=datetime.utcnow(),
        artist=kanye, # Assign the artist object directly
    )
    love_lockdown = Song(
        filename='love_lockdown.mp3',
        title='Love Lockdown',
        date_added=datetime.utcnow(),
        artist=kanye,
    )

    requiem = Song(
        filename='requiem.mp3',
        title='Requiem',
        date_added=datetime.utcnow(),
        artist=mozart,
    )

    # Add songs to the DB session and flush to generate their primary key IDs
    # as well as populating the artist_id field
    session.add(stronger)
    session.add(love_lockdown)
    session.add(requiem)
    session.flush()

    # Create a playlist
    playlist = Playlist(name='test')
    session.add(playlist)
    session.flush()

    # Add some songs to the playlist
    playlist.append_song(stronger)
    playlist.append_song(love_lockdown)
    playlist.append_song(requiem)

    # Delete a song from the playlist
    playlist.delete_song(1)

    # Insert a song at number 3 in the playlist
    playlist.insert_song(2, love_lockdown)

    session.commit()

    print "Artists: %s, %s" % (kanye, mozart)
    print "Each artist's songs: Kanye: %s, Mozart: %s" % (kanye.songs, mozart.songs)
    print "Playlist songs: %s" % playlist.songs
def activity_example():
    # Create pace objects and add to session
    slow, steady, fast, sprint = Pace(speed='Slow'), Pace(speed='Steady'), \
        Pace(speed='Fast'), Pace(speed='Sprint')

    session.add(slow)
    session.add(steady)
    session.add(fast)
    session.add(sprint)

    # Create an activity plan
    plan = ActivityPlan(name='test')
    session.add(plan)
    session.flush()

    # Add 4 segments to the plan
    plan.append_segment(pace=steady, length=60)
    plan.append_segment(pace=steady, length=60)
    plan.append_segment(pace=slow, length=10)
    plan.append_segment(pace=sprint, length=60)

    # Whoops - I made a mistake and want to delete a segment!
    plan.delete_segment(1)

    # Fix the second segment
    plan.update_segment(position=1, pace=fast, length=60)

    # Add a segment to the beginning
    plan.insert_segment(position=0, pace=slow, length=60)
    session.flush()
    session.commit()

    # Clean up orphaned segments
    Segment.remove_orphans()

    session.commit()

    print "Plan segments: %s" % plan.segments
def activity_example():
    # Create pace objects and add to session
    slow, steady, fast, sprint = Pace(speed='Slow'), Pace(speed='Steady'), \
        Pace(speed='Fast'), Pace(speed='Sprint')

    session.add(slow)
    session.add(steady)
    session.add(fast)
    session.add(sprint)

    # Create an activity plan
    plan = ActivityPlan(name='test')
    session.add(plan)
    session.flush()

    # Add 4 segments to the plan
    plan.append_segment(pace=steady, length=60)
    plan.append_segment(pace=steady, length=60)
    plan.append_segment(pace=slow, length=10)
    plan.append_segment(pace=sprint, length=60)

    # Whoops - I made a mistake and want to delete a segment!
    plan.delete_segment(1)

    # Fix the second segment
    plan.update_segment(position=1, pace=fast, length=60)

    # Add a segment to the beginning
    plan.insert_segment(position=0, pace=slow, length=60)
    session.flush()
    session.commit()

    # Clean up orphaned segments
    Segment.remove_orphans()

    session.commit()

    print "Plan segments: %s" % plan.segments
Beispiel #19
0
def csv_import():
    """
    Import the song metadata from song_dict.csv into the database.
    """
    print "Importing CSV song data into the database..."
    csvfile = open('song_dict.csv', 'r')
    csvreader = csv.reader(csvfile, delimiter=',', quotechar='\"')
    artist_dict = {}
    for title, artist_name, bpm, duration, filename in csvreader:
        # Create or fetch artist
        artist_name = artist_name.decode('utf-8')
        artist = artist_dict.get(artist_name)
        if not artist:
            # Create new artist
            artist = Artist(name=artist_name)

            # Add artists to the DB session and flush to generate their
            # primary key IDs
            session.add(artist)
            session.flush()

            # Remember the artist via the artists dict
            artist_dict[artist_name] = artist

        # Create songs
        song = Song(
            filename=os.path.abspath(filename.decode('utf-8')),
            title=title.decode('utf-8'),
            date_added=datetime.utcnow(),
            artist=artist,  # Assign the artist object directly
        )

        # Add songs to the DB session and flush to generate their
        # primary key IDs as well as populating the artist_id field
        print "Adding song %s..." % song
        session.add(song)
        session.flush()

        # Create Metadata
        meta = SongMeta(
            duration=int(float(duration)),
            bpm=int(bpm),
            song=song,
        )
        session.add(meta)
        session.flush()

    session.commit()
    print "CSV import finished successfully."
Beispiel #20
0
def csv_import():
    """
    Import the song metadata from song_dict.csv into the database.
    """
    print "Importing CSV song data into the database..."
    csvfile = open('song_dict.csv', 'r')
    csvreader = csv.reader(csvfile, delimiter=',', quotechar = '\"')
    artist_dict = {}
    for title, artist_name, bpm, duration, filename in csvreader:
        # Create or fetch artist
        artist_name = artist_name.decode('utf-8')
        artist = artist_dict.get(artist_name)
        if not artist:
            # Create new artist
            artist = Artist(name=artist_name)

            # Add artists to the DB session and flush to generate their
            # primary key IDs
            session.add(artist)
            session.flush()

            # Remember the artist via the artists dict
            artist_dict[artist_name] = artist

        # Create songs
        song = Song(
            filename = os.path.abspath(filename.decode('utf-8')),
            title = title.decode('utf-8'),
            date_added = datetime.utcnow(),
            artist = artist, # Assign the artist object directly
        )

        # Add songs to the DB session and flush to generate their
        # primary key IDs as well as populating the artist_id field
        print "Adding song %s..." % song
        session.add(song)
        session.flush()

        # Create Metadata
        meta = SongMeta(
            duration = int(float(duration)),
            bpm = int(bpm),
            song = song,
        )
        session.add(meta)
        session.flush()

    session.commit()
    print "CSV import finished successfully."
Beispiel #21
0
    def generate(self, plan):
        """
        Generate a playlist of songs given a plan.
        """
        def get_current_set(sets, pace):
            """
            Return the set of songs for the given Pace if non-empty, otherwise
            choose sets in increasing order of speed until a non-empty set is
            found. If all sets are empty, return `None`.

            Nested because it only makes sense to use this within generate().
            """
            if sets[pace]:
                # Current set is non-empty - guard statement returns early
                return sets[pace]

            # The set for the current segment pace is empty - choose the
            # next fastest set
            print "    NO SONGS LEFT IN CURRENT SET %s! Choosing a new set" % pace
            paces = PACE_ENUM.keys()
            for _ in xrange(4):
                # Get new pace using the PACE_ENUM.
                # Choose the next paces in increasing speed order, unless the
                # current pace is a Sprint, in which case we wrap around to Slow.
                pace = paces[(paces.index(pace) + 1) % 4] # modulo to wrap around to Slow
                if sets[pace]:
                    # We have found a non-empty set - continue with this
                    print "        Found nonempty set %s" % pace
                    return sets[pace]
            else:
                # At this point NONE of the pace sets had any songs left,
                # which means we have exhausted our corpus of songs.
                # Break here - the playlist is finished as there's nothing
                # left to add.
                print "        ALL SETS EXHAUSTED"
                return None


        # Reset the playlist, just in case!
        for _ in xrange(len(self.playlist_songs)):
            ps = self.playlist_songs.pop()
            session.delete(ps)
        self.playlist_songs = []
        session.flush()

        slow_set, steady_set, fast_set, sprint_set = self.divide_songs_into_sets()
        # Add sets to a dict to easily access by hash
        sets = {
            'Slow': slow_set,
            'Steady': steady_set,
            'Fast': fast_set,
            'Sprint': sprint_set,
        }

        segments = list(plan.segments)
        remaining_segments = len(segments)
        remaining_time = segments[0].length
        skips = 0

        for seg in segments:
            if skips > 0:
                # Skip this segment if a song overlaps it completely
                skips -= 1
                continue

            print "NEW SEGMENT: %s" % seg
            remaining_segments -= 1
            pace = seg.pace.speed

            current_set = get_current_set(sets, pace)
            if not current_set:
                # We have exhausted the corpus of songs! Our playlist is finished
                break

            # Pick subset of songs that can fit in the time remaining
            subset = [
                song
                for song in current_set
                if song.meta.duration <= remaining_time
            ]

            while subset:
                # Pick a random song
                song = random.choice(subset)

                # Add the song to our playlist
                print "    Adding song from subset: %s" % song
                self.append_song(song)

                # Remove the song from relevant sets
                subset.remove(song)
                current_set.remove(song)

                # Recalculate time remaining
                remaining_time -= song.meta.duration

                # Remove any songs that are greater than the remaining time
                subset = [
                    song
                    for song in subset
                    if song.meta.duration <= remaining_time
                ]

            # At this point the segment cannot fit any more segments without
            # overlapping with the next segment.
            print "    Cannot fit any more whole songs in this segment."

            # It's possible at this point that the current set has been exhausted
            # of songs, so we check to see if we need to get the next nonempty set
            current_set = get_current_set(sets, pace)
            if not current_set:
                # No more songs
                break

            if remaining_time == 0 and remaining_segments > 0:
                # Just go to the next seg - set remaining_time to that segment's
                # duration
                remaining_time = segments[seg.position + 1].length
                print "        Moving to next segment"
            elif remaining_segments == 0:
                # Our run is almost done - pick a random song at the current
                # segment pace
                song = random.choice(current_set)
                self.append_song(song)
                current_set.remove(song)
                print "        THIS IS THE LAST SEGMENT. Adding random song"
            else:
                # We will (potentially) have to overlap with the next segment.
                next_seg = segments[seg.position + 1]
                if PACE_ENUM[next_seg.pace.speed] > PACE_ENUM[seg.pace.speed] \
                        and current_set[0].meta.duration / 2 > remaining_time:
                    # The next segment is at a faster pace.
                    # Here we choose a song from the current segment's set iff
                    # 50% or more of the song will take place in the current
                    # segment.
                    # Otherwise, pick the shortest song from the current pace's
                    # set, so we minimize the amount of time the song cuts into
                    # the next segment
                    current_set = get_current_set(sets, next_seg.pace.speed)
                    if not current_set:
                        # No more songs
                        break

                song = current_set[0]
                self.append_song(song)
                current_set.remove(song)
                print "        Add song from curr pace."

                # Calculate the overlap between the last song of this segment
                # and the next segment
                overlap = (song.meta.duration - remaining_time)
                next_seg_position = seg.position + 1
                remaining_time = segments[next_seg_position].length - overlap
                while remaining_time <= 0:
                    # If the song completely overlaps the next segment, skip it
                    # and consider the segment after that, until we no longer
                    # completely overlap any segments.
                    print "SKIPPING %s" % segments[next_seg_position]
                    skips += 1
                    remaining_segments -= 1
                    if remaining_segments == 0:
                        # We have already overlapped the last segment, so no more
                        # songs are needed
                        return
                    next_seg_position += 1
                    overlap = abs(remaining_time)
                    remaining_time = segments[next_seg_position].length - overlap

        self.write_playlist_to_file()
Beispiel #22
0
    def generate(self, plan):
        """
        Generate a playlist of songs given a plan.
        """
        def get_current_set(sets, pace):
            """
            Return the set of songs for the given Pace if non-empty, otherwise
            choose sets in increasing order of speed until a non-empty set is
            found. If all sets are empty, return `None`.

            Nested because it only makes sense to use this within generate().
            """
            if sets[pace]:
                # Current set is non-empty - guard statement returns early
                return sets[pace]

            # The set for the current segment pace is empty - choose the
            # next fastest set
            print "    NO SONGS LEFT IN CURRENT SET %s! Choosing a new set" % pace
            paces = PACE_ENUM.keys()
            for _ in xrange(4):
                # Get new pace using the PACE_ENUM.
                # Choose the next paces in increasing speed order, unless the
                # current pace is a Sprint, in which case we wrap around to Slow.
                pace = paces[(paces.index(pace) + 1) %
                             4]  # modulo to wrap around to Slow
                if sets[pace]:
                    # We have found a non-empty set - continue with this
                    print "        Found nonempty set %s" % pace
                    return sets[pace]
            else:
                # At this point NONE of the pace sets had any songs left,
                # which means we have exhausted our corpus of songs.
                # Break here - the playlist is finished as there's nothing
                # left to add.
                print "        ALL SETS EXHAUSTED"
                return None

        # Reset the playlist, just in case!
        for _ in xrange(len(self.playlist_songs)):
            ps = self.playlist_songs.pop()
            session.delete(ps)
        self.playlist_songs = []
        session.flush()

        slow_set, steady_set, fast_set, sprint_set = self.divide_songs_into_sets(
        )
        # Add sets to a dict to easily access by hash
        sets = {
            'Slow': slow_set,
            'Steady': steady_set,
            'Fast': fast_set,
            'Sprint': sprint_set,
        }

        segments = list(plan.segments)
        remaining_segments = len(segments)
        remaining_time = segments[0].length
        skips = 0

        for seg in segments:
            if skips > 0:
                # Skip this segment if a song overlaps it completely
                skips -= 1
                continue

            print "NEW SEGMENT: %s" % seg
            remaining_segments -= 1
            pace = seg.pace.speed

            current_set = get_current_set(sets, pace)
            if not current_set:
                # We have exhausted the corpus of songs! Our playlist is finished
                break

            # Pick subset of songs that can fit in the time remaining
            subset = [
                song for song in current_set
                if song.meta.duration <= remaining_time
            ]

            while subset:
                # Pick a random song
                song = random.choice(subset)

                # Add the song to our playlist
                print "    Adding song from subset: %s" % song
                self.append_song(song)

                # Remove the song from relevant sets
                subset.remove(song)
                current_set.remove(song)

                # Recalculate time remaining
                remaining_time -= song.meta.duration

                # Remove any songs that are greater than the remaining time
                subset = [
                    song for song in subset
                    if song.meta.duration <= remaining_time
                ]

            # At this point the segment cannot fit any more segments without
            # overlapping with the next segment.
            print "    Cannot fit any more whole songs in this segment."

            # It's possible at this point that the current set has been exhausted
            # of songs, so we check to see if we need to get the next nonempty set
            current_set = get_current_set(sets, pace)
            if not current_set:
                # No more songs
                break

            if remaining_time == 0 and remaining_segments > 0:
                # Just go to the next seg - set remaining_time to that segment's
                # duration
                remaining_time = segments[seg.position + 1].length
                print "        Moving to next segment"
            elif remaining_segments == 0:
                # Our run is almost done - pick a random song at the current
                # segment pace
                song = random.choice(current_set)
                self.append_song(song)
                current_set.remove(song)
                print "        THIS IS THE LAST SEGMENT. Adding random song"
            else:
                # We will (potentially) have to overlap with the next segment.
                next_seg = segments[seg.position + 1]
                if PACE_ENUM[next_seg.pace.speed] > PACE_ENUM[seg.pace.speed] \
                        and current_set[0].meta.duration / 2 > remaining_time:
                    # The next segment is at a faster pace.
                    # Here we choose a song from the current segment's set iff
                    # 50% or more of the song will take place in the current
                    # segment.
                    # Otherwise, pick the shortest song from the current pace's
                    # set, so we minimize the amount of time the song cuts into
                    # the next segment
                    current_set = get_current_set(sets, next_seg.pace.speed)
                    if not current_set:
                        # No more songs
                        break

                song = current_set[0]
                self.append_song(song)
                current_set.remove(song)
                print "        Add song from curr pace."

                # Calculate the overlap between the last song of this segment
                # and the next segment
                overlap = (song.meta.duration - remaining_time)
                next_seg_position = seg.position + 1
                remaining_time = segments[next_seg_position].length - overlap
                while remaining_time <= 0:
                    # If the song completely overlaps the next segment, skip it
                    # and consider the segment after that, until we no longer
                    # completely overlap any segments.
                    print "SKIPPING %s" % segments[next_seg_position]
                    skips += 1
                    remaining_segments -= 1
                    if remaining_segments == 0:
                        # We have already overlapped the last segment, so no more
                        # songs are needed
                        return
                    next_seg_position += 1
                    overlap = abs(remaining_time)
                    remaining_time = segments[
                        next_seg_position].length - overlap

        self.write_playlist_to_file()
 def append_segment(self, pace, length):
     """
     Append a segment to the list with pace `pace` and length `length`.
     """
     self.segments.append(Segment(pace=pace, length=length))
     session.flush()
Beispiel #24
0
 def append_segment(self, pace, length):
     """
     Append a segment to the list with pace `pace` and length `length`.
     """
     self.segments.append(Segment(pace=pace, length=length))
     session.flush()