source: trunk/Piece.py @ 1374

Revision 1374, 7.9 KB checked in by laszlo, 13 years ago (diff)

fixed #1142 spent: 12h

  • Property svn:eol-style set to native
Line 
1# Copyright 2006 by the LeMill Team (see AUTHORS)
2#
3# This file is part of LeMill.
4#
5# LeMill is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# LeMill is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with LeMill; if not, write to the Free Software
17# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
19from SharedMetadata import *
20from Products.Archetypes.public import *
21from Globals import InitializeClass
22from Products.CMFCore.utils import getToolByName
23from AccessControl import ClassSecurityInfo, Unauthorized
24from config import PROJECTNAME, VIEW
25from FieldsWidgets import WYSIWYMField, WYSIWYMWidget
26from Resources import Resource
27from mp3tool import get_length
28import cStringIO
29try:
30    from PIL import Image
31except ImportError:
32    pass
33
34schema = BaseSchema + description + tags + author_schema + original_author_schema + piece_license_schema + coverImage + contentFile + sourceFile + lemill_metadata_mods + deletionReason 
35
36schema = schema + Schema((
37    ImageField('image',
38               required=False,
39               accessor='getImage',
40               mutator='setImage',
41               sizes={'small':(120,120),'medium':(240,240),'large':(500,500)},
42               widget = ImageWidget(visible={'view':'invisible','edit':'invisible'}),
43               ),
44    ImageField('imageJpeg', # required for building Pilot flash animations
45               required=False,
46               default_content_type = 'image/jpeg',
47               allowable_content_types = ('image/jpeg',),
48               original_size=(500,375),
49               widget = ImageWidget(visible={'view':'invisible','edit':'invisible'}),
50               ),
51
52    IntegerField('length',
53               required=False,
54               default=0,
55               widget = LabelWidget(
56                    label = "Playing time",
57                    label_msgid = "label_playing_time",
58                    i18n_domain = "lemill",
59                    visible={'view':'visible', 'edit':'invisible'},
60               ))
61    ))
62
63schema = schema.copy()
64schema.__delitem__('language')
65schema.moveField('rights', pos='bottom')
66
67class Piece(Resource):
68    """Piece"""
69    schema = schema
70
71    actions= (
72    {
73    'id':'edit',
74    'name':'Edit',
75    'action':'string:${object_url}/piece_edit',
76    'permission':('View',),
77    },
78    )
79
80
81    meta_type = "Piece"
82    archetype_name = "Piece"
83    security = ClassSecurityInfo()
84    security.declareObjectPublic()
85
86    aliases = {
87        '(Default)' : 'base_view',
88        'view'      : 'base_view',
89        'edit'      : 'piece_edit'
90    }
91
92       
93    # Use the file as cover image, if it's an image
94    def setFile(self,value,**kwargs):
95        file=self.getField('file')
96        # Call normal mutator for this field
97        file.set(self,value,**kwargs)
98        if file.getContentType(self).startswith('image/'):
99            # Call mutator for the coverImage field as well
100            cover=self.getField('coverImage')
101            cover.set(self,value,**kwargs)
102            # set 'hasCoverImage'-flag
103            has_cover=self.getField('hasCoverImage')
104            has_cover.set(self,True)
105            # Populate the image field
106            image=self.getField('image')
107            image.set(self,value,**kwargs)
108            # we also need 500x500 jpg for every image..
109            #<--comment this out because we don't need to make these until asked with get-method... should speed up updating archetypes.
110            #image_jpeg=self.getField('image_jpeg')
111            #image_jpeg.set(self,value,**kwargs)
112        if file.getContentType(self).startswith('audio/mpeg'):
113            length=self.getField('length')
114            try:
115                length.set(self,self.getMp3Length(), **kwargs)
116            except:
117                print 'something went wrong with setting mp3 length'
118
119
120    def pretty_title_or_id(self):
121        """Return modified title."""
122        return '[P] ' + self.Title()
123
124    def getLength(self):
125        """get stored length of audio piece or try to calculate it """
126        length=self.getField('length').get(self)
127        file=self.getField('file')
128        if length==0 and file.getContentType(self).startswith('audio/mpeg'):
129            length=self.getMp3Length()
130            self.setLength(length)
131        if length==0:
132            return 30
133        else:
134            return length
135           
136
137    def isImage(self):
138        """Returns whether the piece is an image."""
139        file=self.getField('file')
140        return file.getContentType(self).startswith('image/')
141
142    def isAudio(self):
143        """Returns whether the piece is an audio file. """
144        file=self.getField('file')
145        return file.getContentType(self).startswith('audio/')
146
147    def isMovie(self):
148        """Returns whether the piece is an movie file. (not tested) """
149        file=self.getField('file')
150        return file.getContentType(self).startswith('movie/')
151   
152    def isFLVVideo(self):
153        """Returns whether the piece is an FLV video."""
154        file=self.getField('file');
155        file=file.get(self, raw=True, unwrapped=True)
156        file=file.aq_self
157        file=str(file)
158        return file.startswith('FLV');
159       
160    def getMp3Length(self):
161        """Calling out for our custom mp3tool"""
162        print 'calculating length for mp3 %s' % self.getId()
163        file=self.getField('file')
164        file=file.get(self, raw=True, unwrapped=True)
165        file=file.aq_self
166        file=str(file)
167        try:
168            length=get_length(file)
169        except:
170            length=0
171            print 'calculating mp3 length failed for %s' % self.id
172        return length
173
174
175    def getJpegVarName(self):
176        """ 'image_large' if image is originally jpeg,
177        'image_jpeg' if not (this is special image field, where jpeg version of original is stored)
178        gives strings because these are only parts of urls that are passed to flash """
179        file=self.getField('file')
180        if file==None: return None
181        if not file.getContentType(self).startswith('image/'):
182            print 'why getJpegVarName was called for non-image piece? in %s' % self.getId()
183            return None # this shouldn't happen
184        if file.getContentType(self)=='image/jpeg':
185            return 'image_large'       
186        field=self.getField('imageJpeg')
187        val=self.image_jpeg
188        if len(val)>0 and field.getContentType(self)=='image/jpeg': # not sure about that len
189            return 'imageJpeg'
190        else:
191            value=file.get(self)
192            try:
193                value=self._convertToJpg(value)
194            except:
195                print 'error converting image to jpg'
196                return 'image_large'
197            field.set(self, value)
198            return 'imageJpeg'
199
200    def _convertToJpg(self, value):
201        val = value.data
202        s = cStringIO.StringIO(val)
203        s.seek(0)
204        im = Image.open(s)
205        original_mode = im.mode
206        if original_mode == '1':
207            im = im.convert('L')
208        elif original_mode == 'P':
209            im = im.convert('RGBA')
210        s = cStringIO.StringIO()
211        im.save(s, "jpeg")
212        s.seek(0)
213        value=s.read()
214        return value
215
216    def getDefaultIcon(self, meta_type='', obj=None):
217        """ Names for icons are not anymore algorithmically derived """
218        if self.isAudio():
219            return 'images/default_soundclip.png'
220        elif self.isMovie():
221            return 'images/default_movieclip.png'
222        else:
223            # images should always have coverimages and this method shouldn't even get called
224            return 'images/default_learningresource.png'
225       
226       
227registerType(Piece, PROJECTNAME)
Note: See TracBrowser for help on using the repository browser.