Skip to content

Commit

Permalink
more initial stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
tpetr committed Nov 22, 2010
1 parent a19e74e commit 86ea589
Show file tree
Hide file tree
Showing 32 changed files with 537 additions and 0 deletions.
1 change: 1 addition & 0 deletions etc/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.sqlite
1 change: 1 addition & 0 deletions lib/mutagen
Empty file added muxlist/__init__.py
Empty file.
Empty file added muxlist/account/__init__.py
Empty file.
25 changes: 25 additions & 0 deletions muxlist/account/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from django.db import models
from django.contrib.auth.models import User

class UserProfile(models.Model):
user = models.OneToOneField(User)
parent = models.ForeignKey('self', blank=True, null=True)
uploaded_tracks = models.ManyToManyField('music.Track', blank=True, related_name='uploader')
favorite_tracks = models.ManyToManyField('music.Track', blank=True, related_name='favorited')

def __unicode__(self):
return user.__unicode__(self)

def create_userprofile(sender, instance, created, **kwargs):
if created:
print "Making userprofile"
UserProfile.objects.create(user=instance)

models.signals.post_save.connect(create_userprofile, sender=User)

class Invite(models.Model):
owner = models.ForeignKey(User)
code = models.CharField(max_length=16, unique=True, db_index=True)

def __unicode__(self):
return u"%s - %s" % (self.owner, self.code)
23 changes: 23 additions & 0 deletions muxlist/account/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""
This file demonstrates two different styles of tests (one doctest and one
unittest). These will both pass when you run "manage.py test".
Replace these with more appropriate tests for your application.
"""

from django.test import TestCase

class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
"""
self.failUnlessEqual(1 + 1, 2)

__test__ = {"doctest": """
Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2
True
"""}

6 changes: 6 additions & 0 deletions muxlist/account/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.conf.urls.defaults import *

urlpatterns = patterns('',
(r'^login/$', 'django.contrib.auth.views.login', {'template_name': 'account/login.html'}),
(r'^logout/$', 'django.contrib.auth.views.logout', {'template_name': 'account/logout.html'}),
)
1 change: 1 addition & 0 deletions muxlist/account/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Create your views here.
17 changes: 17 additions & 0 deletions muxlist/manage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env python2.6
import os, sys
ROOT_PATH = os.path.abspath("%s/.." % os.path.dirname(__file__))

if os.path.join(ROOT_PATH, 'lib/') not in sys.path:
sys.path.insert(0, os.path.join(ROOT_PATH, 'lib/'))

from django.core.management import execute_manager
try:
import settings # Assumed to be in the same directory.
except ImportError:
import sys
sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
sys.exit(1)

if __name__ == "__main__":
execute_manager(settings)
Empty file added muxlist/mix/__init__.py
Empty file.
8 changes: 8 additions & 0 deletions muxlist/mix/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from django.contrib import admin
from muxlist.mix.models import Group, PlaylistEntry

class PlaylistEntryAdmin(admin.ModelAdmin):
list_display = ('group', 'user', 'index', 'track')

admin.site.register(Group)
admin.site.register(PlaylistEntry, PlaylistEntryAdmin)
34 changes: 34 additions & 0 deletions muxlist/mix/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from django.db import models
from django.contrib.auth.models import User

class Group(models.Model):
name = models.CharField(max_length=128, unique=True, db_index=True)
collaborators = models.ManyToManyField(User, blank=True, related_name="membership")
round_robin_count = models.PositiveSmallIntegerField(default=1, blank=True)
enqueued_tracks = models.PositiveSmallIntegerField(default=0, blank=True)

is_active = models.BooleanField(default=False, blank=True)
is_public = models.BooleanField(default=False, blank=True)
started_on = models.DateTimeField(blank=True)
current_index = models.PositiveSmallIntegerField(default=1, blank=True)

created_on = models.DateTimeField(auto_now_add=True)
last_updated = models.DateTimeField(auto_now=True)

def __unicode__(self):
return self.name

class PlaylistEntry(models.Model):
user = models.ForeignKey(User)
group = models.ForeignKey(Group, related_name='entries')
track = models.ForeignKey('music.Track')
index = models.PositiveSmallIntegerField()

created_on = models.DateTimeField(auto_now_add=True)

def __unicode__(self):
return u"%s - %s (%s #%s)" % (self.group, self.track, self.user, self.index)

class Meta:
ordering = ['group', 'index', 'user__id']
unique_together = ('group', 'user', 'index')
23 changes: 23 additions & 0 deletions muxlist/mix/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""
This file demonstrates two different styles of tests (one doctest and one
unittest). These will both pass when you run "manage.py test".
Replace these with more appropriate tests for your application.
"""

from django.test import TestCase

class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
"""
self.failUnlessEqual(1 + 1, 2)

__test__ = {"doctest": """
Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2
True
"""}

6 changes: 6 additions & 0 deletions muxlist/mix/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.conf.urls.defaults import *

urlpatterns = patterns('muxlist.mix.views',
(r'^(?P<group_name>.*)/xspf$', 'xspf'),
(r'^(?P<group_name>.*)/$', 'index'),
)
19 changes: 19 additions & 0 deletions muxlist/mix/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from django.http import HttpResponse
from django.shortcuts import render_to_response, get_object_or_404
from muxlist.mix.models import Group
from muxlist.music.forms import UploadForm
from django.contrib.auth.decorators import login_required

def index(request, group_name):
group = get_object_or_404(Group, name=group_name)
if not (group.is_public or (request.user.is_authenticated() and request.user in group.collaborators.all())):
return HttpResponseRedirect('/account/login?next=%s' % request.path)
entries = group.entries.all()
form = UploadForm()
return render_to_response('mix/group.html', {'group': group, 'entries': entries, 'form': form, 'user': request.user})

def xspf(request, group_name):
group = get_object_or_404(Group, name=group_name)
if not (group.is_public or (request.user.is_authenticated() and request.user in group.collaborators.all())):
return HttpResponseRedirect('/account/login?next=%s' % request.path)
return render_to_response('mix/xspf.xml', {'entries': group.entries.all()}, mimetype="application/xspf+xml")
Empty file added muxlist/music/__init__.py
Empty file.
7 changes: 7 additions & 0 deletions muxlist/music/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from django.contrib import admin
from muxlist.music.models import Artist, Album, Track, TrackLocation

admin.site.register(Artist)
admin.site.register(Album)
admin.site.register(Track)
admin.site.register(TrackLocation)
44 changes: 44 additions & 0 deletions muxlist/music/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from django import forms
from muxlist.music.models import Track, TrackLocation, Artist, Album
from muxlist.mix.models import Group, PlaylistEntry

from muxlist.music.util import get_track_data_from_url

from django.db.models import Max

class UploadForm(forms.Form):
url = forms.URLField()
group = forms.ModelChoiceField(label="", queryset=Group.objects.all(), widget=forms.HiddenInput(), required=False)

def save(self, user):
try:
tl = TrackLocation.objects.get(url=self.cleaned_data['url'])
track = tl.track
except TrackLocation.DoesNotExist:
tl = TrackLocation(url=self.cleaned_data['url'])

artist_name, album_name, track_name, year, hash = get_track_data_from_url(self.cleaned_data['url'])


if artist_name != '':
artist = Artist.objects.get_or_create(name=artist_name)[0]
else:
artist = None

if album_name != '':
album = Album.objects.get_or_create(artist=artist, name=album_name)[0]
else:
album = None

track = Track.objects.get_or_create(title=track_name, album=album, year=year, artist=artist)[0]

tl.track = track
tl.save()

user.get_profile().uploaded_tracks.add(track)


if self.cleaned_data['group']:
index = (PlaylistEntry.objects.filter(user=user, group=self.cleaned_data['group']).aggregate(Max('index'))['index__max'] or 0) + 1
pe = PlaylistEntry(user=user, group=self.cleaned_data['group'], track=track, index=index)
pe.save()
50 changes: 50 additions & 0 deletions muxlist/music/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from django.db import models

class Artist(models.Model):
name = models.CharField(max_length=128)

created_on = models.DateTimeField(auto_now_add=True)
last_updated = models.DateTimeField(auto_now=True, auto_now_add=True)

def __unicode__(self):
return self.name

class Album(models.Model):
name = models.CharField(max_length=128)
artist = models.ForeignKey(Artist, related_name='albums')
year = models.PositiveSmallIntegerField(blank=True, null=True)

created_on = models.DateTimeField(auto_now_add=True)
last_updated = models.DateTimeField(auto_now=True, auto_now_add=True)

def __unicode__(self):
return u"%s [%s]" % (self.name, self.year)

class Track(models.Model):
title = models.CharField(max_length=128)
album = models.ForeignKey(Album, related_name='tracks', blank=True, null=True)
year = models.PositiveSmallIntegerField(blank=True, null=True)
artist = models.ForeignKey(Artist, related_name='tracks', blank=True, null=True)

hash = models.CharField(max_length=32, blank=True, null=True)

created_on = models.DateTimeField(auto_now_add=True)
last_updated = models.DateTimeField(auto_now=True, auto_now_add=True)

def get_location(self):
return self.locations.filter(active=True)[0]

def __unicode__(self):
return u"%s - %s" % (self.artist.name, self.title)

class TrackLocation(models.Model):
url = models.URLField(max_length=128)
track = models.ForeignKey(Track, related_name='locations')

active = models.BooleanField(default=True, blank=True)

created_on = models.DateTimeField(auto_now_add=True)
last_updated = models.DateTimeField(auto_now_add=True, auto_now=True)

def __unicode__(self):
return self.url
23 changes: 23 additions & 0 deletions muxlist/music/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""
This file demonstrates two different styles of tests (one doctest and one
unittest). These will both pass when you run "manage.py test".
Replace these with more appropriate tests for your application.
"""

from django.test import TestCase

class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
"""
self.failUnlessEqual(1 + 1, 2)

__test__ = {"doctest": """
Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2
True
"""}

6 changes: 6 additions & 0 deletions muxlist/music/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.conf.urls.defaults import *

urlpatterns = patterns('muxlist.music.views',
(r'^$', 'index'),
(r'^upload/?$', 'upload'),
)
37 changes: 37 additions & 0 deletions muxlist/music/util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import urllib, urllib2
from mutagen.easyid3 import EasyID3

def get_track_data_from_url(url):
request = urllib2.Request(url)

byte_count = 500

while True:
print "Trying %s bytes" % byte_count
request.add_header('Range', 'bytes=0-%s' % byte_count)

response = urllib2.urlopen(request)

fp = open("/tmp/test.mp3", "wb")
fp.write(response.read())
fp.close()

try:
audio = EasyID3("/tmp/test.mp3")
break
except EOFError:
byte_count += 10000

artist = audio['artist']
if isinstance(artist, list): artist = artist[0]

album = audio.get('album', '')
if isinstance(album, list): album = album[0]

title = audio['title']
if isinstance(title, list): title = title[0]

year = audio.get('date', None)
if isinstance(year, list): year = year[0]

return (artist, album, title, year, None)
23 changes: 23 additions & 0 deletions muxlist/music/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render_to_response
from django.contrib.auth.decorators import login_required

from muxlist.music.forms import UploadForm

@login_required
def index(request):
profile = request.user.get_profile()
form = UploadForm()
return render_to_response('music/index.html', {'user': request.user, 'uploaded_tracks': profile.uploaded_tracks.all(), 'favorite_tracks': profile.favorite_tracks.all(), 'form': form, 'groups': request.user.membership.all()})

@login_required
def upload(request):
if request.method == 'POST':
form = UploadForm(data=request.POST, files=request.FILES)
if form.is_valid():
form.save(user=request.user)
return HttpResponseRedirect(request.REQUEST.get('next', ''))
else:
form = UploadForm()

return render_to_response('music/upload.html', {'form': form})
Loading

0 comments on commit 86ea589

Please sign in to comment.