From f67a1150e9f23c8b23e83b10cc97b2a43d59215f Mon Sep 17 00:00:00 2001 From: Antoine van Gelder Date: Tue, 30 Oct 2007 20:45:00 +0000 Subject: * Feature: If no sound set, play default sound: laugh_attack.au * Fixed: Activity icon now adopts users color scheme * Fixed: Temp directory now rooted off activity.get_activity_root() * Fixed: Moved locale/ dir back to po/ * Fixed: Temp filenames now created using more secure tempfile.mkstemp() * i18n: Changed pot files to utf-8 --- diff --git a/JokeMachineActivity.py b/JokeMachineActivity.py index 3259a9e..654d3e7 100644 --- a/JokeMachineActivity.py +++ b/JokeMachineActivity.py @@ -72,8 +72,8 @@ class JokeMachineActivity(activity.Activity): # TODO - clean - install gettext os.chdir(Globals.pwd) # required for i18n.py to work - #gettext.install('JokeMachine', './locale', unicode=True) - #presLan_af = gettext.translation("JokeMachine", os.path.join(Globals.pwd, 'locale'), languages=['af']) + #gettext.install('JokeMachine', './po', unicode=True) + #presLan_af = gettext.translation("JokeMachine", os.path.join(Globals.pwd, 'po'), languages=['af']) #presLan_af.install() #locale.setlocale(locale.LC_ALL, 'af') diff --git a/MANIFEST b/MANIFEST index 9baeaa2..672900b 100644 --- a/MANIFEST +++ b/MANIFEST @@ -10,16 +10,17 @@ ./i18n.py ./i18n_misc_strings.py ./resources/GameLogoCharacter.png -./resources/image.png ./resources/audio.png +./resources/image.png +./resources/laugh_attack.au ./lessons/Introduction/default.abw ./lessons/Lesson 1/default.abw ./lessons/Lesson 2/default.abw ./lessons/Lesson 3/default.abw ./lessons/Lesson 4/default.abw -./locale/JokeMachine.pot -./locale/af/LC_MESSAGES/JokeMachine.mo -./locale/af/LC_MESSAGES/JokeMachine.po +./po/JokeMachine.pot +./po/af/LC_MESSAGES/JokeMachine.mo +./po/af/LC_MESSAGES/JokeMachine.po ./mesh/__init__.py ./mesh/activitysession.py ./pages/__init__.py @@ -34,6 +35,7 @@ ./persistence/jokebook.py ./persistence/jokemachinestate.py ./setup.py +./tmp/.keep ./util/__init__.py ./util/audioplayer.py ./util/decorators.py diff --git a/NEWS b/NEWS index e310a8d..f153344 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,20 @@ -4 + + * Feature: If no sound set, play default sound: laugh_attack.au + * Fixed: Activity icon now adopts users color scheme + * Fixed: Temp directory now rooted off activity.get_activity_root() + * Fixed: Moved locale/ dir back to po/ + * Fixed: Temp filenames now created using more secure tempfile.mkstemp() + * i18n: Changed pot files to utf-8 + + -- Antoine van Gelder Mon, 29 Oct 2007 + + +JokeMachine-4.xo + + * Tested: Build# 622 and sugar-jhbuild + + -- Antoine van Gelder Mon, 29 Oct 2007 + JokeMachine-3.xo @@ -12,7 +28,7 @@ JokeMachine-3.xo * Fixed: Don't hardcode JokeEditor delete button position * Fixed: On read jokebook & empty -> "Edit My Jokes" -> Go to edit my jokes tab * Updated :Mesh code for dbus tubes changes - + -- Antoine van Gelder Mon, 29 Oct 2007 diff --git a/TODO b/TODO index 0685638..076d749 100644 --- a/TODO +++ b/TODO @@ -1,17 +1,19 @@ = To Do = -* Figure out why only alerts are being translated +* Figure out why only alerts are being translated * Double check that all strings are gettexted * Use hippo.PACK_EXPAND to get rid of hardcoded sizes * Get a fix on memory useage * Create and set activity_version property for persistence.JokeMachineState.version * Split unit.py out into separate test cases -* Refactor Page.make_* infrastructure +* Sundry refactors +* Figure out a safe way to clean out /activity_root/tmp on startup * Things waiting for the journal to settle ** Filter ObjectChooser to only list images/audio -> https://dev.laptop.org/ticket/3060 ** Create sample Jokebooks in the journal on bundle installation +** Insert sample laugh tracks into the journal on bundle installation ** Fold image/image_blob into a single property ** Fold sound/sound_blob into a single property ** Bring up the last Jokebooks instead of starting from scratch when started from the frame @@ -21,8 +23,4 @@ = Known Problems = * i18n is only translating alerts at the moment for some strange reason -* AudioPlayer dumps files into /tmp which may be problematic for security system * Deprecating theme_widget() for custom gtkrc fixes language combo but there are now faint hints of Irish in the activity frame :) - - - diff --git a/activity/activity-jokemachine.svg b/activity/activity-jokemachine.svg index a8c7c4a..b10dadb 100644 --- a/activity/activity-jokemachine.svg +++ b/activity/activity-jokemachine.svg @@ -3,30 +3,34 @@ -]> - - - - - - - - - - - - - + + +]> + + + + + + + + + + + + + + + + + diff --git a/globals.py b/globals.py index 5cadaeb..0a6d2e6 100644 --- a/globals.py +++ b/globals.py @@ -16,6 +16,7 @@ import os import logging +import tempfile from sugar.activity import activity try: from hashlib import sha1 @@ -32,7 +33,9 @@ class __globals(object): def __init__(self): self.__pwd = activity.get_bundle_path() + self.__root = None self.__logo = 'resources/GameLogoCharacter.png' + self.__laugh = 'resources/laugh_attack.au' self.__activity_state = None self.__activity = None @@ -46,6 +49,7 @@ class __globals(object): # convert all of these to @Property def set_activity_instance(self, activity_instance): logging.debug('setting actifity %r' % activity_instance) + self.__root = activity_instance.get_activity_root() self.__activity = activity_instance # TODO -> Should we refresh the GUI for this one ? @@ -62,19 +66,28 @@ class __globals(object): return self.__pwd @property + def root(self): + return self.__root + + @property def tmpdir(self): '''Temporary directory - currently this exists for the sole purpose of having a place to dump sounds and images into so we don't have to keep them in memory - don't know if this will still be valid under bitfrost, don't know if sounds and images can be pulled directly out of the journal when needing to be (dis)played''' - return '/tmp' #os.path.join(self.__pwd, 'tmp') + logging.debug('Temp dir is %s' % os.path.join(self.__root, 'tmp')) + return os.path.join(self.__root, 'tmp') @property def logo(self): return os.path.join(self.pwd, self.__logo) @property + def laugh_uri(self): + return os.path.join(self.pwd, self.__laugh) + + @property def JokeMachineState(self): if not self.__activity_state: # Okay - When app is not run from Journal activity.read_file() is never @@ -100,10 +113,9 @@ class __globals(object): # utility functions with global state def temporary_filename(self): - # TODO - remember these and delete them all on app exit - file_name = os.tempnam(self.tmpdir) - self.__temporary_filenames.append(file_name) - return file_name + (fd, name) = tempfile.mkstemp(prefix='jokemachine_') + self.__temporary_filenames.append(name) + return name def shutdown(self): diff --git a/i18n.py b/i18n.py index aaf42c8..546893e 100644 --- a/i18n.py +++ b/i18n.py @@ -72,7 +72,7 @@ class LangDetails (object): self.image = image def guess_translation (self, fallback=False): - self.gnutranslation = gettext.translation('JokeMachine', './locale', [self.code], fallback=fallback) + self.gnutranslation = gettext.translation('JokeMachine', './po', [self.code], fallback=fallback) def install (self): self.gnutranslation.install() @@ -97,7 +97,7 @@ def get_lang_details (lang): def list_available_translations (): rv = [get_lang_details('en')] rv[0].guess_translation(True) - for i,x in enumerate([x for x in os.listdir('locale') if os.path.isdir('locale/' + x) and not x.startswith('.')]): + for i,x in enumerate([x for x in os.listdir('po') if os.path.isdir('po/' + x) and not x.startswith('.')]): try: details = get_lang_details(x) if details is not None: diff --git a/locale/af/LC_MESSAGES/JokeMachine.mo b/locale/af/LC_MESSAGES/JokeMachine.mo deleted file mode 100644 index 7fac1bc..0000000 --- a/locale/af/LC_MESSAGES/JokeMachine.mo +++ /dev/null Binary files differ diff --git a/pages/joke.py b/pages/joke.py index 43d0764..ee92fb8 100644 --- a/pages/joke.py +++ b/pages/joke.py @@ -19,6 +19,7 @@ import gtk import hippo import pango from gettext import gettext as _ +import logging from globals import Globals from gui.page import Page @@ -134,11 +135,14 @@ class Joke(Page): def __do_clicked_answer(self, button, jokebook, joke_id): # play a sound if the jokebook has one + player = AudioPlayer() if jokebook.sound_blob != None: - player = AudioPlayer() player.raw = jokebook.sound_blob - player.play() - + else: # default laugh + logging.debug('Playing default sound: %s', Globals.laugh_uri) + player.uri = Globals.laugh_uri + player.play() + # show the answer self.joke_box.answer_box.set_visible(True) diff --git a/locale/JokeMachine.pot b/po/JokeMachine.pot index 93dcf91..1d309c1 100644 --- a/locale/JokeMachine.pot +++ b/po/JokeMachine.pot @@ -8,20 +8,20 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2007-10-29 05:52+0200\n" +"POT-Creation-Date: 2007-10-30 22:32+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=CHARSET\n" -"Content-Transfer-Encoding: 8bit\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: UTF-8\n" -#: activity/activity.info:2 JokeMachineActivity.py:123 +#: activity/activity.info:2 JokeMachineActivity.py:128 #: mesh/activitysession.py:165 mesh/activitysession.py:205 msgid "Joke Machine" msgstr "" -#: JokeMachineActivity.py:123 +#: JokeMachineActivity.py:128 msgid "Please wait a moment for your buddy's Jokebooks to show up" msgstr "" @@ -257,35 +257,35 @@ msgstr "" msgid "Accept" msgstr "" -#: pages/joke.py:56 +#: pages/joke.py:57 msgid "Joke" msgstr "" -#: pages/joke.py:59 +#: pages/joke.py:60 msgid "By" msgstr "" -#: pages/joke.py:69 pages/submit.py:63 +#: pages/joke.py:70 pages/submit.py:63 msgid "Question" msgstr "" -#: pages/joke.py:78 pages/joke.py:123 pages/submit.py:71 +#: pages/joke.py:79 pages/joke.py:124 pages/submit.py:71 msgid "Answer" msgstr "" -#: pages/joke.py:97 +#: pages/joke.py:98 msgid "This Jokebook is empty" msgstr "" -#: pages/joke.py:99 pages/joke.py:156 +#: pages/joke.py:100 pages/joke.py:160 msgid "Submit a Joke" msgstr "" -#: pages/joke.py:104 +#: pages/joke.py:105 msgid "Add Jokes" msgstr "" -#: pages/joke.py:150 +#: pages/joke.py:154 msgid "Next" msgstr "" diff --git a/po/af/LC_MESSAGES/JokeMachine.mo b/po/af/LC_MESSAGES/JokeMachine.mo new file mode 100644 index 0000000..f2a2854 --- /dev/null +++ b/po/af/LC_MESSAGES/JokeMachine.mo Binary files differ diff --git a/locale/af/LC_MESSAGES/JokeMachine.po b/po/af/LC_MESSAGES/JokeMachine.po index 3682935..bccd5e5 100644 --- a/locale/af/LC_MESSAGES/JokeMachine.po +++ b/po/af/LC_MESSAGES/JokeMachine.po @@ -5,22 +5,22 @@ # msgid "" msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" +"Project-Id-Version: 5\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2007-10-29 05:52+0200\n" "PO-Revision-Date: 2007-10-29 05:53+0200\n" -"Last-Translator: \n" +"Last-Translator: Antoine van Gelder \n" "Language-Team: Afrikaans\n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=ASCII\n" -"Content-Transfer-Encoding: 8bit\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: UTF-8\n" -#: activity/activity.info:2 JokeMachineActivity.py:123 +#: activity/activity.info:2 JokeMachineActivity.py:128 #: mesh/activitysession.py:165 mesh/activitysession.py:205 msgid "Joke Machine" msgstr "Grap Masjien" -#: JokeMachineActivity.py:123 +#: JokeMachineActivity.py:128 msgid "Please wait a moment for your buddy's Jokebooks to show up" msgstr "Wag asseblief 'n oomblik vir jou maaitjie se grap boek" @@ -256,35 +256,35 @@ msgstr "Nie Aanvaar" msgid "Accept" msgstr "Aanvaar" -#: pages/joke.py:56 +#: pages/joke.py:57 msgid "Joke" msgstr "Grap" -#: pages/joke.py:59 +#: pages/joke.py:60 msgid "By" msgstr "By" -#: pages/joke.py:69 pages/submit.py:63 +#: pages/joke.py:70 pages/submit.py:63 msgid "Question" msgstr "Vraag" -#: pages/joke.py:78 pages/joke.py:123 pages/submit.py:71 +#: pages/joke.py:79 pages/joke.py:124 pages/submit.py:71 msgid "Answer" msgstr "Antwoord" -#: pages/joke.py:97 +#: pages/joke.py:98 msgid "This Jokebook is empty" msgstr "Hierdie Grapboek is leeg" -#: pages/joke.py:99 pages/joke.py:156 +#: pages/joke.py:100 pages/joke.py:160 msgid "Submit a Joke" msgstr "Stuur 'n Grappie" -#: pages/joke.py:104 +#: pages/joke.py:105 msgid "Add Jokes" msgstr "Voeg grap by" -#: pages/joke.py:150 +#: pages/joke.py:154 msgid "Next" msgstr "Volgende" diff --git a/resources/laugh_attack.au b/resources/laugh_attack.au new file mode 100644 index 0000000..d0e5875 --- /dev/null +++ b/resources/laugh_attack.au Binary files differ diff --git a/tmp/.keep b/tmp/.keep new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tmp/.keep diff --git a/unit/unit.py b/unit/unit.py index cf06715..e8eba7b 100755 --- a/unit/unit.py +++ b/unit/unit.py @@ -32,6 +32,16 @@ from util.decorators import Property # test Property decorator # + +from util.audioplayer import AudioPlayer + +audio = AudioPlayer() +#audio.uri = '/home/antoine/Projects/dev.laptop.org/sugar-jhbuild/build/share/activities/JokeMachine.activity/resources/laugh_attack.wav' +audio.uri = '/home/antoine/Projects/dev.laptop.org/sugar-jhbuild/source/sugar/data/startup.flac' +audio.play() + +sys.exit() + #class Foo(object): #@Property diff --git a/util/audioplayer.py b/util/audioplayer.py index 911fa42..dacf51f 100644 --- a/util/audioplayer.py +++ b/util/audioplayer.py @@ -23,19 +23,19 @@ from util.decorators import Property class AudioPlayer(object): - + def __init__(self): pass - - + + @Property def uri(): def get(self): return self.__uri def set(self, value): if value is None or not os.path.exists(value): - logging.error('AudioPlayer- Invalid URI: %r', value) - return - self.__uri = value + logging.error('AudioPlayer - Invalid URI: %r', value) + return + self.__uri = value size = os.path.getsize(self.__uri) self.pipeline.get_by_name('source').set_property('location', self.__uri) self.pipeline.get_by_name('source').set_property('mmapsize', size) @@ -45,28 +45,26 @@ class AudioPlayer(object): def raw(): def get(self): if self.uri is None: - logging.error('AudioPlayer - No data') - return None + logging.error('AudioPlayer - No data') + return None f = open(self.uri, 'r') raw = f.read() f.close() return raw def set(self, value): - temp = Globals.temporary_filename() - f = open(temp, 'w') + name = Globals.temporary_filename() + f = open(name, 'w') f.write(value) f.close() - #self.source.set_property('location', temp) - #self.source.set_property('mmapsize', len(value)) - self.uri = temp - logging.debug('AudioPlayer - set_raw wrote %d bytes to %s', len(value), temp) + self.uri = name + logging.debug('AudioPlayer - set_raw wrote %d bytes to %s', len(value), name) @Property def pipeline(): def get(self): if self.__pipeline is None: - self.__pipeline = self.__build_pipeline() + self.__pipeline = self.__build_pipeline() return self.__pipeline @@ -80,11 +78,11 @@ class AudioPlayer(object): def __build_pipeline(self): # pipeline pipeline = gst.Pipeline('pipeline') - + # add source source = gst.element_factory_make('filesrc', 'source') pipeline.add(source) - + # add decoder decoder = gst.element_factory_make('decodebin', 'decoder') decoder.connect("new-decoded-pad", self.__new_decoded_pad) #, converter) @@ -94,27 +92,27 @@ class AudioPlayer(object): # add converter converter = gst.element_factory_make("audioconvert", "converter") pipeline.add(converter) - + # add output sink = gst.element_factory_make('autoaudiosink', 'sink') pipeline.add(sink) converter.link(sink) - + bus = pipeline.get_bus() bus.add_signal_watch() bus.connect('message', self.__on_audio_message) - + return pipeline - - + + # callbacks ################################################################## - + def __new_decoded_pad(self, dbin, pad, islast): #, converter) converter = self.pipeline.get_by_name('converter') # TODO - pass by arg pad.link(converter.get_pad("sink")) - - + + def __on_audio_message(self, bus, message): t = message.type #logging.debug('message: %r' % t) -- cgit v0.9.1