Hi again Kristian,
If you don't already have a deferred handy, you need to create one
(which is obviously what you're doing) to return properly from a method
that is expected to return a deferred.
There are shortcut to do that, which are
twisted.internet.defer.succeed() and .fail() (see
http://twistedmatrix.com/documents/current/api/twisted.internet.defer.html#succeed).
In your case, since you do not seem to do anything asynchronous, you do
not need to create that "play_uri()" subfunction. You can implement what
it does idrectly in node_clicked() and return something with
defer.succeed() in the end, typically:
return defer.succeed(None)
Ensuring you have imported the defer module from twisted.internet.
Guillaume
Le vendredi 06 février 2009 à 22:04 +0100, Kristian Lippert a écrit :
> Hi Olivier
> With your help it was easy to make some code that python liked:
>
> def node_clicked(self, widget, item):
>
> def play_uri(self=dfr_self, station=dfr_station):
> player =
> self.frontend.retrieve_controllers('/poblesec/music_player')[0]
> player.player.play_model(station)
> main = self.frontend.retrieve_controllers('/poblesec')[0]
> main.show_music_player()
> self.stop_loading_animation()
>
> dfr = defer.Deferred().addCallback(play_uri, self, item)
> return dfr
>
> But the play is not called (and you stated there is no magic :-)
> But when looking into the shoutcast play-method that is called
> implicit using some sort of Elisa command pattern I see the following:
>
> def play_station(self, station):
> resource, dfr =
> application.resource_manager.get(station.get_playable, station)
>
> def play(station):
> player =
> self.frontend.retrieve_controllers('/poblesec/music_player')[0]
> player.player.play_model(station)
>
> main = self.frontend.retrieve_controllers('/poblesec')[0]
> main.show_music_player()
> self.stop_loading_animation()
>
> dfr.addCallback(play)
>
> As seen a deferred comes "magically" (:-) in hand and the method
> "play" is added.
> I would like to do the same but have no resource in the resource
> manager (I think??)
>
> Please Advice!
>
> Best Regards,
> Kristian
> > Date: Wed, 4 Feb 2009 09:50:22 +0100
> > From: [email protected]
> > To: [email protected]
> > CC: [email protected]
> > Subject: Re: [Elisa] Problems with deferred and Elisa
> >
> > Hi Kristian,
> >
> > Kristian Lippert a écrit :
> > > Hi
> > > I have a play-method in my own stream-player and it works:
> > >
> > > def node_clicked(self, widget, item):
> > > def play_uri(self, station):
> > > # We already know the real URL of the playable audio stream, no
> > > # need to query the resource manager
> > > # get player and start playing
> > > player =
> > > self.frontend.retrieve_controllers('/poblesec/music_player')[0]
> > > player.player.play_model(station)
> > > main = self.frontend.retrieve_controllers('/poblesec')[0]
> > > main.show_music_player()
> > > self.stop_loading_animation()
> > >
> > > pdb.set_trace()
> > > if isinstance(item, Action):
> > > item.run()
> >
> > Side note: this test is useless if you know that your list contains
> only
> > PlayableModels.
> >
> > > elif isinstance(item, PlayableModel):
> > > play_uri(self, item)
> > >
> > > It works fine but if there are problems with the stream it will
> hang for
> > > a while, so I thought I could use a deferred, like:
> > >
> > > def node_clicked(self, widget, item):
> > >
> > > def play_uri(self, station):
> > > # We already know the real URL of the playable audio stream, no
> > > # need to query the resource manager
> > > # get player and start playing
> > > player =
> > > self.frontend.retrieve_controllers('/poblesec/music_player')[0]
> > > player.player.play_model(station)
> > >
> > > main = self.frontend.retrieve_controllers('/poblesec')[0]
> > > main.show_music_player()
> > > self.stop_loading_animation()
> > >
> > > pdb.set_trace()
> > > if isinstance(item, Action):
> > > item.run()
> > > elif isinstance(item, PlayableModel):
> > > dfr = defer.Deferred().addCallback(play_uri)
> > > return dfr(self, item)
> > >
> > > My problem is that I am not sure:
> > > 1) Do I create the deferred in the right manner?
> >
> > Not really, see my explanation below.
> >
> > > 2) How does the binding of the parameters happen?
> >
> > Simply pass extra arguments to the addCallback method, they are
> going to
> > be passed to the callback after the result argument.
> >
> > > 3) Do I need to activate the deferred my self or will this happen
> by
> > > magic by it self?
> >
> > If you instantiate a deferred with defer.Deferred(), then nothing
> won't
> > happen until someone/something invokes its callback() method, that
> will
> > in turn trigger the chained callbacks to be called.
> >
> > One simple example:
> >
> > def cb(result, arg1, arg2):
> > print result, arg1, arg2
> >
> > dfr = defer.Deferred()
> > dfr.addCallback(cb, 'hello', 'world')
> > dfr.callback()
> >
> > If you want to try it out as is in a python shell, you'll have to
> import
> > twisted.internet.reactor, and call reactor.run().
> >
> > > As far as I can read the deferred can be compared to the .NET
> > > asynchronous delegates or boost::thread. Boost::thread is much
> simpler
> > > but they share the problem regarding binding variables.
> >
> > Unfortunately deferreds won't magically make synchronous code
> > asynchronous. They are a tool to help you write asynchronous code,
> but
> > in that case the underlying methods you are calling
> > (player.player.play_model, main.show_music_player,
> > self.stop_loading_animation) are all synchronous (in the sense that
> they
> > don't return a deferred). You could mock asynchrony by calling them
> in a
> > thread, but that's highly discouraged so I'm not giving you the link
> to
> > the doc of the method that allows that ;)
> >
> > > Please help me fix the code!
> > >
> > > Best Regards,
> > > Kristian
> >
> > I hope this helps.
> >
> > Olivier
>
>
> ______________________________________________________________________
> Invite your mail contacts to join your friends list with Windows Live
> Spaces. It's easy! Try it!