tag:blogger.com,1999:blog-19073721572329638502024-03-14T12:44:39.035+01:00Stephane's logStephanehttp://www.blogger.com/profile/13725417672949898970noreply@blogger.comBlogger30125tag:blogger.com,1999:blog-1907372157232963850.post-42456259429703996012013-09-26T14:54:00.000+02:002013-09-26T14:54:26.503+02:00SpriteKit on Xamarin.iOS: fun without compromiseTL;DR: get the source of the game on <a href="https://github.com/StephaneDelcroix/SpriteKitDemo">github</a>.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitx4ytNblxeQ4KAi4P1E7T67mv0-KDt9u3mwrpLV7dw9EiHT2aDu7lQBNhSRiz_qwnln4GKV7X76w-Nu7ZAm1LJHnNjBR6Y7mStUdYw-Ak5-gp9kJs3OnPR-Ag4lEDjW42gLnkf1nM3Ag/s1600/photo.PNG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitx4ytNblxeQ4KAi4P1E7T67mv0-KDt9u3mwrpLV7dw9EiHT2aDu7lQBNhSRiz_qwnln4GKV7X76w-Nu7ZAm1LJHnNjBR6Y7mStUdYw-Ak5-gp9kJs3OnPR-Ag4lEDjW42gLnkf1nM3Ag/s320/photo.PNG" width="213" /></a></div>
<br />
With the release of iOS7, and <a href="http://blog.xamarin.com/ios-7-and-xamarin-ready-when-you-are/">same day support in Xamarin.iOS</a>, I'm spending all my free time playing with the new APIs. I particularly love iBeacon and Background Fetch. Next on my list was SpriteKit.<br />
<br />
SpriteKit is a 2D game engine, not unlike cocos2d at all. We'll see next that it's going from one platform to another is very simple.<br />
<br />
I'm not a game developer, but I have some experience with cocos2d as I co-wrote (with <a href="https://twitter.com/migueldeicaza">Miguel</a>) the <a href="https://github.com/mono/monotouch-bindings/tree/master/cocos2d">cocos2d bindings for Xamarin.iOS</a>. At that time, to test the binding, I ported a sample platform jumper game from obj-c cocos2d to <a href="https://github.com/mono/monotouch-bindings/tree/master/cocos2d/samples/Jumpy">c#</a>. And I again ported the same game to SpriteKit. Here are my findings about the experience:<br />
<br />
<h3>
The Pros</h3>
<br />
<ul>
<li>you can almost to a line by line port between cocos2d and SpriteKit, once you figure out the basics</li>
<li>less boilerplate. Or even no boilerplate at all with SpriteKit. a SKView is a UIView, and is ready to serve as soon as you PresentScene() it. Compare that with the directors you have to put in place before writing a line of game logic in cocos2d. It's a win.</li>
<li>less leaky abstractions. I haven't compared performances, but SpriteKit doesn't expose stuffs like BatchNodes, so it's one stuff you don't have to bother about.</li>
<li>SKAction is a nice addition for objects you don't want to animate yourself in your Update() loop (they're executed just after Update(), and before physics simulation)</li>
</ul>
<br />
<h3>
The Cons</h3>
<br />
<ul>
<li>I found myself looking for BitmapFonts. It seems like a standard in game development, but missing from SpriteKit (or I haven't found it). I'm quite confident that's a stuff we'll see in an upcoming new version.</li>
</ul>
<br />
<h3>
The Rest</h3>
<br />
<ul>
<li>As the original game, this port doesn't leverage any Physics engine, so I have nothing to say about SKPhysics* stuffs. From the API, it looks very similar to what Chipmunk offer.</li>
</ul>
<div>
<br /></div>
<div>
So it was a very pleasant port, at the end taking even less lines of code than the original port, and only 2 hours to write. If you want to start developing games, going for SpriteKit on Xamarin.iOS is really a no brainer. No boilerplate, no gotchas, just fun.</div>
<br />
<h3>
The Code</h3>
The code is on <a href="https://github.com/StephaneDelcroix/SpriteKitDemo">github</a>, it's MIT/X11 so do whatever you want with it. The graphics are borrowed from the original game, read the <a href="https://github.com/StephaneDelcroix/SpriteKitDemo/blob/master/LICENSE">LICENSE</a> about their usage.Stephanehttp://www.blogger.com/profile/13725417672949898970noreply@blogger.com0tag:blogger.com,1999:blog-1907372157232963850.post-66379821576393852542013-09-24T10:59:00.001+02:002013-09-24T10:59:42.381+02:00Xamarin.iOS 7 : iBeacons - Part 1: AdvertizingOne of my favorite new feature of iOS 7 is the addition of iBeacons. You'll find plenty of articles explaining how it'll change the way you do shopping (if you still shop offline), allows indoor localization, and even more. Glue a beacon on your kids, and you'll know when they go too far away (digital leash). Attach one to your wallet and your phone will tell you you're leaving the house with no cash. Applications are endless.<br />
<br />
iBeacons is a protocol on top of Bluetooth LE (Low Energy, also advertised as Bluetooth Smart, and part of the Bluetooth 4.0). It doesn't require any new hardware and is nothing really new by itself. What's new and exciting is its position in iOS: first-class citizen, integrated with CoreLocation, working in the background, ...<br />
<br />
<h3>
The recipe: advertising your position</h3>
<div>
As of now, the only objects you can use as iBeacons are iOS devices. The protocol should be made available soon, allowing 3rd party components to appear, and at that time they should sell for a few dollars a piece (based on a general purpose BT chip, like the <a href="http://www.bluegiga.com/en-US/products/bluetooth-4.0-modules/ble112-bluetooth--smart-module/">BLE112</a>, a beacon should cost around 40$ to build. Prices will surely drop by using cheaper and specialized chips).</div>
<div>
<br /></div>
<div>
Turning your iOS device into a beacon is really only a few steps:<br />
<h3>
1. Initialize a CLBeaconRegion</h3>
<div>
That'll be your beacon. uuid and identifier are mandatory. Major and minor are optional. There's a trick here, uuid doesn't have to be unique. All beacons of a common group will probably have the same uuid, and different major/minor versions.</div>
<div>
<br /></div>
<div>
<code>
var beaconId = new NSUuid ("5a2bf809-992f-42c2-8590-6793ecbe2437"); //uuidgen on MacOS, nguid in VS<br />
var beaconRegion = new CLBeaconRegion (beaconId, "yourOrg.yourBeacon");
</code>
</div>
<h3>
2. Initialize a CBPeripheralManager</h3>
<div>
<code>
var peripheralManager = new CLPeripheralManager (new PeripheralManagerDelegate(beaconRegion), DispatchQueue.DefaultGlobalQueue, new NSDictionary ());<br />
<br />
class PeripheralManagerDelegate : CBPeripheralManagerDelegate<br />
{<br />
CLBeaconRegion beaconRegion;<br />
<br />
public CBPeripheralManager (CLBeaconRegion beaconRegion)<br />
this.beaconRegion = beaconRegion;<br />
}<br />
<br />
public override void StateUpdated (CBPeripheralManager peripheralManager)<br />
{<br />
//State will be Unsupported on devices like iPhone4 and prior, PoweredOff if BT is down<br />
if (peripheralManager.State != CBPeripheralManagerState.PoweredOn)<br />
return;<br />
var options = beaconRegion.GetPeripheralData (null);<br />
peripheralManager.StartAdvertizing (options);<br />
}<br />
}<br />
</code>
</div>
<br />
<div>
And that's it.<br />
<br />
<h3>
Notes and further reading</h3>
<br />
<ul>
<li>As devices BT ids changes from time to time, your device will be sometimes advertised twice. That won't happen with real iBeacons.</li>
<li>If you want to advertize in the Background, enable "Acts as Bluetooth LE accessory" in your info.plist</li>
<li>Read <a href="https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/LocationAwarenessPG/RegionMonitoring/RegionMonitoring.html">Region Monitoring</a> if you need more details.</li>
</ul>
<br />
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<br /></div>
Stephanehttp://www.blogger.com/profile/13725417672949898970noreply@blogger.com0tag:blogger.com,1999:blog-1907372157232963850.post-71933700155013944032013-05-08T15:00:00.000+02:002013-05-08T15:00:03.386+02:00It's all about monkeys<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXTP_12wIQuAbjExgA9-3BsdTOQH7ShPYft317v0LHvYJIm0Zq2rc6CJP6RbSQXW1cQEjwWhtjVkIcXrpVmcsJ6LzJ94g2ApGIMUXwJNWN2fjnUPWdsXes5eUx7-G2pu1xmN-HZW2_xPc/s1600/IMG_9583.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXTP_12wIQuAbjExgA9-3BsdTOQH7ShPYft317v0LHvYJIm0Zq2rc6CJP6RbSQXW1cQEjwWhtjVkIcXrpVmcsJ6LzJ94g2ApGIMUXwJNWN2fjnUPWdsXes5eUx7-G2pu1xmN-HZW2_xPc/s320/IMG_9583.jpg" width="320" /></a></div>
Yesterday evening, May 7, two belgian user groups, <a href="http://madn.be/">MADN</a> and <a href="http://www.dotnethub.be/">DotNetHub</a> invited me to give a 2 hour introduction session on creating multi-platforms mobile applications in c# with Xamarin 2.0.<br />
<br />
Microsoft Belgium was hosting the session, and the room was packed !<br />
<br />
I really enjoyed that evening, and just wanted to thank you all: attendees for their presence and interactions, MADN and DNH for the invite and the bottle of wine, Microsoft Belgium for the place, food and drinks, and Xamarin for the give away licences, monkeys and t-shirts.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://files.reblochon.org/2013-05-07%20Creating%20xplat%20app%20with%20Xamarin2.0.pdf"><img border="0" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEYtPzl-emzBFTgT5t9IIylTM9KiRrY0wheIncSnna9JNSQbLMxTqqR9lWR7mwu_dXAl4FpJZjaCe7_E8Wi24ilRDueeNN2WFWOVJjhysM73f1X5ipXf89unKot0WPt3QP_U4kwuQ945g/s640/2013-05-08_1019.png" width="640" /></a></div>
<br />Stephanehttp://www.blogger.com/profile/13725417672949898970noreply@blogger.com0tag:blogger.com,1999:blog-1907372157232963850.post-3681285787165801142013-04-26T11:06:00.001+02:002013-04-26T13:44:39.681+02:00Decorating your Xamarin.iOS code with Behaviors<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigxFupaPg-SVNiDv0b4rVV-P1zqkgzv5u0Xba3agW403ZPI9rigq_a0kRu6OgLGy754BTAsEdeOcCI1WSBOPHLRdWZeIWmpcWqpdzWiVU93-UNe7DqQA4k1mQJIeet6TetMSfBPTYe9hI/s1600/photo.JPG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigxFupaPg-SVNiDv0b4rVV-P1zqkgzv5u0Xba3agW403ZPI9rigq_a0kRu6OgLGy754BTAsEdeOcCI1WSBOPHLRdWZeIWmpcWqpdzWiVU93-UNe7DqQA4k1mQJIeet6TetMSfBPTYe9hI/s320/photo.JPG" width="320" /></a></div>
<i>Note: this is the post in which I'm getting out of the closet and make it clear that I had an affair with Silverlight. I'm still thinking about it sometimes, and when I do, this is what happens...</i><br />
<br />
Every time you have to ask your user "What's your favourite colour" or "What is the air-speed velocity of an unladen swallow?" from within your iOS application, you have to ask yourself "Wait, will the field still be visible with the virtual keyboard displayed ?"<br />
<br />
I don't know how <b>you</b> do it (experience sharing is welcome), but me, I do it this way:<br />
<br />
<pre>public override void ViewDidLoad ()
{
base.ViewDidLoad ();
//Set Bindings and Commands
placeField.Bind (ViewModel, "Place");
sendButton.Command (ViewModel.SendCommand);
busyIndicator.Bind (ViewModel, "IsBusy");
//Slide the view on keyboard show/hide
placeField.EditingDidBegin += (sender, e) => {
UIView.BeginAnimations ("keyboardslide");
UIView.SetAnimationCurve (UIViewAnimationCurve.EaseInOut);
UIView.SetAnimationDuration (.3f);
var frame = View.Frame;
frame.Y = -100;
View.Frame = frame;
UIView.CommitAnimations();
};
placeField.EditingDidEnd += (sender, e) => {
UIView.BeginAnimations ("keyboardslide");
UIView.SetAnimationCurve (UIViewAnimationCurve.EaseInOut);
UIView.SetAnimationDuration (.3f);
var frame = View.Frame;
frame.Y = 20;
View.Frame = frame;
UIView.CommitAnimations();
};
}
</pre>
<br />
<a name='more'></a><br />
<br />
It works fine, but looks messy next to readable code setting bindings or commands (those come from a very light Binding library I'm working on). Then yesterday evening, I had a realisation. It looks very similar to Silverlight Behaviors, so this code could just be like:<br />
<br />
<pre> placeField.Attach (new SlideOnEditBehavior (View, defaultPosition:20, alternatePosition:-100));
</pre>
<br />
And the SlideOnEditBehavior is kept aside (<span style="font-size: x-small;"><span style="font-family: Courier New, Courier, monospace;">OnDetaching</span> implementation left out for clarity</span>):<br />
<br />
<pre>public class SlideOnEditBehavior : Behavior<uitextfield>
{
UIView view;
int defaultPosition;
int alternatePosition;
public SlideOnEditBehavior (UIView view, int defaultPosition, int alternatePosition)
{
this.view = view;
this.defaultPosition = defaultPosition;
this.alternatePosition = alternatePosition;
}
protected override void OnAttached ()
{
base.OnAttached ();
AssociatedObject.EditingDidBegin += (sender, e) => {
UIView.BeginAnimations ("keyboardslide");
UIView.SetAnimationCurve (UIViewAnimationCurve.EaseInOut);
UIView.SetAnimationDuration (.3f);
var frame = view.Frame;
frame.Y = alternatePosition;
view.Frame = frame;
UIView.CommitAnimations();
};
AssociatedObject.EditingDidEnd += (sender, e) => {
UIView.BeginAnimations ("keyboardslide");
UIView.SetAnimationCurve (UIViewAnimationCurve.EaseInOut);
UIView.SetAnimationDuration (.3f);
var frame = view.Frame;
frame.Y = defaultPosition;
view.Frame = frame;
UIView.CommitAnimations();
};
}
}
</uitextfield></pre>
<br />
Cleaner. Simpler. Reusable. And it also supports BehaviorCollections:<br />
<br />
<pre> placeField.Attach (new BehaviorCollection {
new SlideOnEditBehavior (View, defaultPosition:20, alternatePosition:-100),
//Any other behavior here
});
</pre>
<br />
As expected, the code for all of this is trivial, but if you like the idea and save yourself the 30 minutes it takes to write it, it's on <a href="https://github.com/StephaneDelcroix/MobileInception.Interactivity">Github</a>.<br />
<br />
[UPDATE: 2013-04-26] I updated the code as per Stuart Lodge suggestion (of MvvmCross) to use WeakReference to NSObjects. Doesn't change the API at all.<br />
<br />
<br />Stephanehttp://www.blogger.com/profile/13725417672949898970noreply@blogger.com3tag:blogger.com,1999:blog-1907372157232963850.post-55672290868330188402013-04-12T15:18:00.000+02:002013-04-12T15:18:38.992+02:00Blogging on topic<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXjFBaBBSK4fiBFVsjACqWZJJrfaI7v0HcPtekg8YenzmmBzBVcGQi6KwpsR9s4gZ_9ExF98-qr4kzh3nmf71k-DbY97qXXSsPokptZQwtWchGcJjkgxWy_Xmj0INWjpqoLOnn4WjvXoQ/s1600/photo-4.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="395" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXjFBaBBSK4fiBFVsjACqWZJJrfaI7v0HcPtekg8YenzmmBzBVcGQi6KwpsR9s4gZ_9ExF98-qr4kzh3nmf71k-DbY97qXXSsPokptZQwtWchGcJjkgxWy_Xmj0INWjpqoLOnn4WjvXoQ/s400/photo-4.JPG" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">A pile of reblochon (get closer, you can smell them)</td></tr>
</tbody></table>
<br />Stephanehttp://www.blogger.com/profile/13725417672949898970noreply@blogger.com1tag:blogger.com,1999:blog-1907372157232963850.post-62209451986394881952013-03-28T15:01:00.000+01:002013-03-28T15:08:01.620+01:00Producing Better Bindings: Completeness<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRRul6g6GgJN6LfcENrpXAUaRZA_9c4QhOFX2lSX6dXeCFY50upzHZyu297pX8FMlsW3TP5c-m5wUEgGoAZ0o3g1fFrR9wcNyXKALyoUpI09xW0Fo6HgP7_r74AA67VMRQNPzm9PhCj8M/s1600/photo-3.JPG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="226" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRRul6g6GgJN6LfcENrpXAUaRZA_9c4QhOFX2lSX6dXeCFY50upzHZyu297pX8FMlsW3TP5c-m5wUEgGoAZ0o3g1fFrR9wcNyXKALyoUpI09xW0Fo6HgP7_r74AA67VMRQNPzm9PhCj8M/s320/photo-3.JPG" width="320" /></a></div>
<i>Note: like the previous <a href="http://blog.reblochon.org/2013/03/await-in-land-of-ios-collisions-in.html">post</a>, this one is a follow-up on a series written by someone else. We're all building on top of giant's shoulders. My giant today is Sébastien Pouliot from <a href="http://xamarin.com/">Xamarin</a>. Read his series <a href="http://blog.xamarin.com/producing-better-bindings-for-xamarin.ios-and-xamarin.mac/">Producing Better Bindings</a>.</i><br />
<i><br /></i>
<i>Second Note: if you're reading this from a news aggregator, you might miss the embedded gists. Read the original <a href="http://blog.reblochon.org/2013/03/producing-better-bindings-completeness.html">there</a>.</i><br />
<br />
I'm lately enjoying writing bindings for Xamarin.iOS and Xamarin.Mac, a lot for the fun, very little for profit. The biggest project by far was creating a managed bindings for cocos2d (v2). This library is huge (~2500 public methods), and the API is far from being fixed in stone. The library is so big that at some point I just gave up, until Miguel resumed the effort during end-of-year break.<br />
<br />
<a name='more'></a><br />
<h3>
No chocolate</h3>
One of my worst nightmare was that, at the point of completion, the API would probably outdated, and going through every .h at every release to check consistency looked very expensive from a maintenance point of view. Hopefully, Sébastien came up with automated tests, removing a lot of the burden. There was still a missing part. making sure we were not missing any (important) part of the exposed API. In <a href="http://blog.xamarin.com/producing-better-bindings-for-xamarin.ios-and-xamarin.mac/">Producing Better Bindings #1</a>, he said:<br />
<blockquote class="tr_bq">
<b>There’s no easy way to test for missing constructors[...]. That would require static analysis (not introspection) in order to be useful.</b></blockquote>
It was very much like a "you can't get chocolate"-day for me. Which means a lot for a Belgian.<br />
<h3>
Static Analysis</h3>
I wanted that feature badly. But I wasn't in the mood of writing (another) .h parser, just to extract the public API (though I could have used the same tools used for generating documentation). So I opted for analysing the generated library, but not at runtime, just after compiling.<br />
<br />
So I added a step in my Makefile that looks like this:<br />
<pre>#static analysis
%.selectors: %.a
nm -P $< | grep "^[-+]\[.*\] t" > $@
</pre>
<br />
which generate a file containing entries like this:<br />
<br />
<pre>+[CCLayerColor layerWithColor:] t b84 0
+[CCLayerColor layerWithColor:width:height:] t b1b 0
-[CCLayerColor blendFunc] t 1167 0
-[CCLayerColor changeHeight:] t ecc 0
-[CCLayerColor changeWidth:] t e87 0
-[CCLayerColor changeWidth:height:] t e4b 0
-[CCLayerColor draw] t fa1 0
-[CCLayerColor initWithColor:] t d81 0
-[CCLayerColor initWithColor:width:height:] t c3f 0
-[CCLayerColor init] t bd7 0
-[CCLayerColor setBlendFunc:] t 1182 0
-[CCLayerColor setColor:] t 10b9 0
-[CCLayerColor setContentSize:] t de2 0
-[CCLayerColor setOpacity:] t 1114 0
-[CCLayerColor updateColor] t f10 0
</pre>
<br />
which is all we need (and some more we don't need).<br />
<h3>
The fixture</h3>
<div>
The <a href="https://github.com/StephaneDelcroix/monotouch-bindings/blob/57d0d6a89e18d48119c2a77f1b02b9b09df07933/cocos2d/binding-test/BindingCompleteness.cs">fixture</a> looks like all other Binding Test fixture. You set <span style="font-family: Courier New, Courier, monospace;">LogProgress</span> and <span style="font-family: Courier New, Courier, monospace;">ContinueOnFailure</span> to the value you want, you override the <span style="font-family: Courier New, Courier, monospace;">Assembly</span> property, and you optionally <span style="font-family: Courier New, Courier, monospace;">Skip()</span> some types.</div>
<h4>
Parsing the file</h4>
<div>
Parsing the generated file isn't part of the <a href="https://github.com/StephaneDelcroix/monotouch-bindings/blob/staticanalysis/cocos2d/binding-test/ApiCompleteness.cs">base fixture</a>, as it's tied to how you extract the selectors; and you have to override <span style="font-family: Courier New, Courier, monospace;">Selectors ()</span>. But if you reuse the Make command, you can also reuse this parser:</div>
<script src="https://gist.github.com/StephaneDelcroix/5263255.js"></script>
<br />
<h4>
Skipping categories</h4>
<div>
If the library you're binding uses categories, like cocos2d does, you can skip full categories:<br />
<br />
<br /></div>
<script src="https://gist.github.com/StephaneDelcroix/22bae38827b1e53920b4.js"></script>
<br />
<h3>
What's missing ?</h3>
<div>
Very few actually. Maybe detecting is all the exposed Fields are bound in your C# API.<br />
<br />
If you liked this post, you probably will also like other stuffs I'm doing. Contact me, I'm open for contracting.</div>
Stephanehttp://www.blogger.com/profile/13725417672949898970noreply@blogger.com0tag:blogger.com,1999:blog-1907372157232963850.post-34426789090127479642013-03-14T13:15:00.002+01:002013-03-14T13:30:30.122+01:00Await in the Land of iOS - Collisions in Chipmunk<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCe3FzmKwvT8zHBhYJAgTYry6N9O70X5Istu6HiGHLxgW0jpet6D3FfvphWBbPE-U8HReu69H1JH_YPpsM3ZVNRLKOVpifZrzmvdN5Om1eglmsaYamFGu2TEZpZ0WwtAp7zDHyAy6W7vg/s1600/DSC_0369.JPG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="193" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCe3FzmKwvT8zHBhYJAgTYry6N9O70X5Istu6HiGHLxgW0jpet6D3FfvphWBbPE-U8HReu69H1JH_YPpsM3ZVNRLKOVpifZrzmvdN5Om1eglmsaYamFGu2TEZpZ0WwtAp7zDHyAy6W7vg/s320/DSC_0369.JPG" width="320" /></a><i>Note: this blog post follows the ones of <a href="http://praeclarum.org/">Frank Krueger</a> about the <a href="http://blog.xamarin.com/brave-new-async-mobile-world/">alpha release of mono 3.x for Xamarin.iOS</a> bringing .NET 4.5 features to the mobile world: <a href="http://praeclarum.org/post/45231096776/await-in-the-land-of-ios-drag-n-drop">Drag-n-drop</a> and <a href="http://praeclarum.org/post/45277337108/await-in-the-land-of-ios-scripting-users">Scripting Users</a>. Read that first, it's worth it.</i><br />
<br />
<h3>
The old way!</h3>
If you're using the <a href="http://blog.reblochon.org/2013/02/chipmunks-bindings-for-monotouch.html">Chipmunk bindings</a>, the correct way to handle collisions between shapes is to register 4 (FOUR!) handlers for the different steps: <b>begin</b>, <b>preSolve</b>, <b>postSolve</b> and <b>separate</b>. Your collision handling logic is then spread in 4 different functions. All of that for the same collision.<br />
<br />
<a name='more'></a><br />
<br />
<pre>bool Begin (Arbiter arb)
{
Console.WriteLine ("began");
return true;
}
bool PreSolve (Arbiter arb)
{
Console.WriteLine ("presolved");
return true;
}
void PostSolve (Arbiter arb)
{
Console.WriteLine ("postsolved");
}
void Separate (Arbiter arb)
{
Console.WriteLine ("separated");
}
</pre>
It would be great, for the sake of simplicity, if we could group the logic altogether.
<br />
<h3>
await to the rescue</h3>
C# 5 (in .NET 4.5) allows just that. Procedural code in the form of:
<br />
<br />
<pre>await began;
Console.WriteLine ("BEGAN");
await presolved;
Console.WriteLine ("PRESOLVE");
await postsolved;
Console.WriteLine ("POSTSOLVE");
await separated;
Console.WriteLine ("SEPARATED");
</pre>
<br />
All this, ran into an infinite loop:<br />
<br />
<pre>async void WaitForCollisions ()
{
using (var waiter = new AsyncCollisionWaiter (space, WALL, CHARACTER)) {
for(;;) {
var began = waiter.GetBeginAsync ();
var presolved = waiter.GetPreSolveAsync ();
var postsolved = waiter.GetPostSolveAsync ();
var separated = waiter.GetSeparateAsync ();
await began;
Console.WriteLine ("BEGAN");
await presolved;
Console.WriteLine ("PRESOLVE");
await postsolved;
Console.WriteLine ("POSTSOLVE");
await separated;
Console.WriteLine ("SEPARATED");
}
}
}
</pre>
<pre></pre>
The magic lies in the AsyncCollisionWaiter. Here's a quick implementation for it<br />
<script src="https://gist.github.com/StephaneDelcroix/5160749.js"></script>
<br />
<h3>
Caveats</h3>
<div>
There's a 5-10 ms delay between the moment the result for the Task is set and the moment the awaiting function is resumed. That means nothing in most cases, but means A LOT when you're simulating physics. That means the <b>separated</b> event happens before the process resumes after the <span style="font-family: Courier New, Courier, monospace;">await began</span>. That's why we have to <span style="font-family: Courier New, Courier, monospace;">Get*Async()</span> all the events we're interested into before waiting for the first one.</div>
<div>
<br /></div>
<div>
Due to that delay as well, we loose the ability to decide in a timely manner if we want this collision to happen or not. That's why I unconditionally return <span style="font-family: Courier New, Courier, monospace;">true</span> from <span style="font-family: Courier New, Courier, monospace;">Begin</span> and <span style="font-family: Courier New, Courier, monospace;">PreSolve</span> in the <span style="font-family: Courier New, Courier, monospace;">AsyncCollisionWaiter</span>.<br />
<br />
<h3>
So what ?</h3>
<div>
Frank got me excited with his series of post. I wanted to apply the same process to my own stuffs. Although the code looks nicer, you're paying a high price for that beauty, and all the value of having 4 events is kinda ruined by the delay. In this case, a single <b>collisionHappened</b> would have been enough.<br />
Have fun experimenting with await in your own mobile application too.</div>
</div>
Stephanehttp://www.blogger.com/profile/13725417672949898970noreply@blogger.com0tag:blogger.com,1999:blog-1907372157232963850.post-65654853945891600762013-03-01T15:41:00.001+01:002013-03-01T15:43:23.148+01:00Working around the reverse callback limitation on Xamarin.iOS<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilesW_pzF7estkgx8fJN2uwHjqyE5Vo3JGftRNnn4igh9se9Y_h4Sc6JYL8hnXv57kUQncrC0e6MjofoU0YCL-RMRrUa10MZCqx7nr9_W7WPgLLRUDFpt7KBOHjfpnkj_mh_6NtpZohUE/s1600/code.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="313" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilesW_pzF7estkgx8fJN2uwHjqyE5Vo3JGftRNnn4igh9se9Y_h4Sc6JYL8hnXv57kUQncrC0e6MjofoU0YCL-RMRrUa10MZCqx7nr9_W7WPgLLRUDFpt7KBOHjfpnkj_mh_6NtpZohUE/s320/code.jpg" width="320" /></a></div>
There's one annoying technical limitation of Xamarin.iOS if you have to pass a C# delegate instance to unmanaged code. It's not new, and it's <a href="http://docs.xamarin.com/guides/ios/advanced_topics/limitations#Reverse_Callbacks">well documented</a>.<br />
<br />
But still, having to flag the callback with an attribute and no instance method makes an API hard to use if you don't care that much about the internals of the library you're consuming.<br />
<br />
I'm currently polishing the Chipmunk binding for Xamarin.iOS, and the cpSpace has some functions taking callbacks, like <span style="font-family: Courier New, Courier, monospace;">cpSpaceEachBody</span> or <span style="font-family: Courier New, Courier, monospace;">cpSpaceAddPostStepCallback</span>.<br />
<br />
<a name='more'></a><br />
<br />
The C# API exposed looks like this (for the PostStep callback):<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">public class Space {</span><span style="font-family: Courier New, Courier, monospace;"> public void AddPostStepCallBack (Action<body> action, Body body);</body></span><span style="font-family: Courier New, Courier, monospace;">}</span></blockquote>
If we could lift the restrictions, it could take lambdas or anonymous methods. This is how I did it behind the scenes:<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">public class Space {<br /> delegate void PostStepFunc (IntPtr space, IntPtr obj, IntPtr data);</span> </blockquote>
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;"> [MonoTouch.MonoPInvokeCallback (typeof (PostStepFunc))]<br /> static void PostStepForBody (IntPtr space, IntPtr obj, IntPtr data)<br /> {<br /> var handle = GCHandle.FromIntPtr (data);<br /> var action = (Action<body>)handle.Target;<br /> handle.Free ();<br /> action (obj == IntPtr.Zero ? null : new Body (obj));<br /> }</body></span> </blockquote>
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;"> [DllImport ("__Internal")]<br /> extern static void cpSpaceAddPostStepCallback (IntPtr space, PostStepFunc func, IntPtr key, IntPtr data); </span> </blockquote>
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;"> public void AddPostStepCallback (Action<body> action, Body obj)<br /> {<br /> var data = GCHandle.ToIntPtr(GCHandle.Alloc (action));<br /> cpSpaceAddPostStepCallback (Handle.Handle, PostStepForBody, obj.Handle.Handle, data);<br /> }<br />}</body></span></blockquote>
Static callback? : Check!<br />
Flagged with attribute? : Check!<br />
<br />
This is possible because of the free to use <span style="font-family: Courier New, Courier, monospace;">data</span> pointer as last argument of the native function call. We don't expose it to the use, and hijack it to pass the <span style="font-family: Courier New, Courier, monospace;">GCHandle</span> ptr of the callback provided by the user.<br />
<br />
Hope it helps you.<br />
<br />
<br />
<br />
Liked this? Want more? I'm available for contracting, so contact me.<br />
<br />
<br />
<br />
<br />Stephanehttp://www.blogger.com/profile/13725417672949898970noreply@blogger.com2tag:blogger.com,1999:blog-1907372157232963850.post-84511450091786713262013-02-11T20:43:00.000+01:002013-03-11T21:29:20.231+01:00Chipmunk bindings for MonoTouch<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8uSDvQuCtlIRWvYWxBGcyj3Vvec8e5s9kfoUeuQhKqPjIdQQ7UTK4YC1r1FWZ3aU_Jf7vXEhSh3NnrlpZdzfmQ2MzUyPuc_-PHj_e8rvZXB3y2Ai0oPDvsI4yLMD3qJ1CRHe_rh3AfVI/s1600/chipmunk.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8uSDvQuCtlIRWvYWxBGcyj3Vvec8e5s9kfoUeuQhKqPjIdQQ7UTK4YC1r1FWZ3aU_Jf7vXEhSh3NnrlpZdzfmQ2MzUyPuc_-PHj_e8rvZXB3y2Ai0oPDvsI4yLMD3qJ1CRHe_rh3AfVI/s1600/chipmunk.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">(c) S. Delcroix 2013</td></tr>
</tbody></table>
I'm quite pleased to announce the availability of <a href="http://chipmunk-physics.net/">Chipmunk</a> bindings for <a href="http://xamarin.com/monotouch">monotouch</a>. I started that last year, and bound just enough of it to get <a href="https://github.com/mono/monotouch-bindings/tree/master/cocos2d/samples/ChipmunkSample">a sample</a> working, added some constraints lately in order to <a href="http://blog.reblochon.org/2013/02/our-business-app-doesnt-need-your-game.html">place labels</a>, and completed it since for the beauty of the task. The image next to this is a screenshot from a system using a motor, a gear joint, pivot joints and some more.<br />
<br />
At this point in time, the ~2000 lines of manually crafted lines of code can be found <strike>in <a href="https://github.com/mono/monotouch-bindings/pull/89">this pull request</a>, but you probably won't have to wait long before it's merged</strike> in the <a href="https://github.com/mono/monotouch-bindings/tree/master/chipmunk">monotouch-bindings repository</a>.<br />
<br />
<a name='more'></a><br />
<br />
<h3>
What's missing ?</h3>
Mainly <a href="http://chipmunk-physics.net/release/ChipmunkLatest-Docs/#Queries">queries</a>, plus a few function calls here and there.<br />
<br />
<h3>
Integrate with cocos2d</h3>
<div>
If you build the Chipmunk bindings from within the mono touch-bindings/cocos2d folder, with ENABLE_CHIPMUNK_INTEGRATION=1, Chipmunk will be build inside of the Cocos2d.dll, and you'll also get the CCPhysicsSprite class acting as integration layer between a Cocos2d sprite and a Chipmunk body.</div>
<br />
<h3>
Memory management</h3>
<div>
tl;dr Always keep a reference to your Space object and you'll be fine.</div>
<div>
<br /></div>
<div>
Multiple Chipmunk managed objects can hold a reference to the same native struct (for example, you could have the object you added to the space, and then another one pointing to the same native ref returned from a callback). As such, we can't free the native memory when a managed object is GC'd. To workaround this, we keep a table of all the managed objects (except for Arbiters) pointing to a native one, and only free the native pointer when the last managed instance is disposed.</div>
<div>
In addition, the Space keep a managed reference to all the Bodies, Shapes and Constraint added, so the native memory isn't freed even if your code doesn't keep a ref to the body/shape/constraint. So, keep a ref to the Space and everything we'll be fine, provided that you create all the Chipmunk objects from the managed side.<br />
<br />
<br />
For more on this, or something totally different, contact me, I'm open for contracting.</div>
Stephanehttp://www.blogger.com/profile/13725417672949898970noreply@blogger.com0tag:blogger.com,1999:blog-1907372157232963850.post-52417347911991813082013-02-05T11:58:00.003+01:002013-02-25T09:38:45.010+01:00Our business app doesn't need your game development skills (using damped springs to place labels on a map)<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjTWDocgdkqzM89xn3zbcgkot7RYHCYuC6IHE65f5CQCf2g5qZg3fk1z5MyKZr1PiZOji0s6MYhgtjsBmiMK8Xul-elowJ79wd1OqOdiW3-nnBSxYtrujqiHUN0myzpajIfFiB3UqXKWU/s1600/spring.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjTWDocgdkqzM89xn3zbcgkot7RYHCYuC6IHE65f5CQCf2g5qZg3fk1z5MyKZr1PiZOji0s6MYhgtjsBmiMK8Xul-elowJ79wd1OqOdiW3-nnBSxYtrujqiHUN0myzpajIfFiB3UqXKWU/s200/spring.jpg" width="111" /></a></div>
<h3>
The problem</h3>
Positioning labels on a map, a chart, a plan is a problem every UI developer face at one time or another if he has the chance to work on rich business app. This problem is <a href="http://en.wikipedia.org/wiki/Automatic_label_placement">NP-Hard for non-trivial cases</a>. I faced that issue twice. First while building a silverlight charting library, and then very recently for positioning labels around a pin on a plan. This post isn't about how we solved those two cases. For the charting problem, we went for an algorithmic solution which was working but not optimal. For the second, I don't know how they solved it as I didn't took the job.<br />
<br />
<a name='more'></a><br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizPL6uPQHjg-yXIHKx4RdSBANJadMvL8nT5LeGF-tBwBYEnUiDCvln5AJjwtfyOYkPORd8FyRgzj_dmFW20nUbiTQdANc6m_3eTX0P_bMbK90Wd4pKHe-ST1kCF2uV7eHEKffy95bScfc/s1600/system.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizPL6uPQHjg-yXIHKx4RdSBANJadMvL8nT5LeGF-tBwBYEnUiDCvln5AJjwtfyOYkPORd8FyRgzj_dmFW20nUbiTQdANc6m_3eTX0P_bMbK90Wd4pKHe-ST1kCF2uV7eHEKffy95bScfc/s1600/system.png" /></a></div>
<h3>
Solution by Physics system</h3>
But the other night, as I contributed <a href="http://chipmunk-physics.net/">Chipmunk</a> bindings to <a href="https://github.com/mono/monotouch-bindings/tree/master/chipmunk">monotouch</a>, one of the reply I got was roughly "I'm not into gaming stuffs, I don't really care. but it looks nice". That got me thinking. First, I'm not a game developer[1][2] neither, and second, you probably should care. One of the most elegant solution I was able to come with for solving a label-positioning problem is to use recipes normally used by game developers. It involves a physics engine, some bodies and some springs.<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRizQNEYZiffn-MAG5ou2_npyAVjCw6ThWpNG3GptVyWFljJsOQMTcGXwiVxYCL33ej0J2jloQHbJ0zSqPnWTIdQfsxOhqP2N7eWquum3m3QGbNh1yW_M87wBEROwZn4_9unQ9Rutvkqc/s1600/2013-02-05_0008.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRizQNEYZiffn-MAG5ou2_npyAVjCw6ThWpNG3GptVyWFljJsOQMTcGXwiVxYCL33ej0J2jloQHbJ0zSqPnWTIdQfsxOhqP2N7eWquum3m3QGbNh1yW_M87wBEROwZn4_9unQ9Rutvkqc/s200/2013-02-05_0008.png" width="102" /></a>Let's say every label you want to position is a physics body with a mass (the same for all the labels), a shape (the rectangle bounding box is a good approximation). Let's say then than all those bodies are attached with a (sampling) spring to the pin. If we run a physics engine on this setup, let the springs pull, let the shapes collide, and it'll stabilise itself to a local optimum. With a some luck, or the right amount of initial entropy, you might even reach the global optimum, but that's not important. Multiples pins with labels close to each other? Check. A lot of labels ? Check. Restrict the labels to a zone or avoid some other? Check, just add constraints or shapes to help the collision algorithms.<br />
<br />
<h3>
Implementation</h3>
But then, how hard is this to implement? If you have a physics engine you can use, this is probably shorter and cleaner to implement than any other method (except the obvious place-at-random-retry-if-it-overlaps). Here's my implementation. It uses monotouch and the <a href="https://github.com/mono/monotouch-bindings/tree/master/chipmunk">chipmunk bindings</a> (<strike>wait for <a href="https://github.com/mono/monotouch-bindings/pull/89">this pull-request</a> to be merged, or get it from my branch</strike> UPDATE 20130225: merged), but using default chipmunk in an obj-C app doesn't take much more:<br />
<br />
<script src="https://gist.github.com/4710666.js"></script>
<br />
<h3>
What next</h3>
Now you can play with the spring parameters and the number of iteration to get the results you expect. You can also use ellipses instead of rectangular bounding boxes. Expect smoother and more natural placement in this case. If you have a lot of labels, use different restLength for the labels you want close to the labels and the one you want a bit farther. A more complex system will take more time (more iterations) to stabilise, so adapt the number of steps, but in any case, keep the dt (time delta) parameter low, experience shows good results between 1/60 and 1/20.<br />
<br />
Want more than this from me ? Contact me, I'm open for contracting.<br />
<br />
<br />
<br />
<span style="font-size: x-small;">[1] I don't like categorisation. Nor being categorised</span><span style="font-size: x-small;">. I'm not an UI dev, I'm not C# dev, I'm not a mobile dev. I'm not even a developer. I have a bagful of hats and wear the ones that gets the job done.</span><br />
<span style="font-size: x-small;">[2] But still, I wrote and tested most of the cocos2d and chipmunk bindings for mono touch, I ported a few games to those platform, and very recently wrote my first game with my 6 y.o. in a day (more on this later).</span><br />
<br />Stephanehttp://www.blogger.com/profile/13725417672949898970noreply@blogger.com2tag:blogger.com,1999:blog-1907372157232963850.post-51280995638047857052013-01-24T12:39:00.000+01:002013-02-25T09:38:57.569+01:00C++ bindings for monotouch using SWIG<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1qQgOa6c_NgceSUcOKr8D69IK8JxngVKheVqS3AEb2vIM7Ezqw2tkgzBr0bOrj9M4bPKeTcEbj5NaL_Pvoe7wga40nWUmesItYzL8DCIEU6gJp4k5YPsGhGEH6orBsWApNm6G6V5f9a4/s1600/coldlight.jpg" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img alt="cold cold light" border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1qQgOa6c_NgceSUcOKr8D69IK8JxngVKheVqS3AEb2vIM7Ezqw2tkgzBr0bOrj9M4bPKeTcEbj5NaL_Pvoe7wga40nWUmesItYzL8DCIEU6gJp4k5YPsGhGEH6orBsWApNm6G6V5f9a4/s320/coldlight.jpg" title="" width="254" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">(c) S. Delcroix 2013</td></tr>
</tbody></table>
I love bindings. I've always loved them. Back in the days, I was binding gtk+ and <a href="https://gitorious.org/unique-sharp/unique-sharp" target="_blank">other</a> <a href="https://gitorious.org/gio-sharp/mainline" target="_blank">gobject</a> libs to C# for fun and f-spot usage. Then I bound some <a href="https://github.com/StephaneDelcroix/PSTCollectionView" target="_blank">obj-C libs to monotouch for a client</a> and some <a href="https://github.com/mono/monotouch-bindings/tree/master/cocos2d" target="_blank">for pleasure</a>.<br />
<br />
But last week I faced something new. I wanted to bind (for <a href="http://xamarin.com/monotouch" target="_blank">monotouch</a>) a C++ iPhone lib for which I only received the binaries and the headers files. The component was too large to even think about doing a manual C glue code. I googled about the possible solutions and the only valuable advice was to <a href="http://stackoverflow.com/a/10254037/1063783" target="_blank">use SWIG</a>, without any rationale or tutorial. This is then probably a first. An explanation on why SWIG can help you for this, the problem I ran into and the solutions I found.<br />
<br />
<a name='more'></a><br />
<br />
<h3>
Mono.Cxxi is sexy, but not all-purpose</h3>
<div>
I'm not the kind of guy who blindly follows recommendations, so my first try was to use anything but SWIG. I opted for <a href="http://tirania.org/blog/archive/2011/Dec-19.html">Mono.Cxxi</a> and created a full binding in a few hours. It was really easy after I figured out the gcc-xml installation steps and caveats with clang. But when I first tried to use inside my monotouch project, it was to no avail. A quick reality-check confirmed my fears:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5_3M7WVdtbZA1PUaGZ3PO4A_orQ23LWENyAANz6rXqzDoHSAA78KQ6ow6f7vngcbDSDt6K4Xs6-Kvd4N-8vp1bXFpbOdn2L6s3YfcsUix6Y7UKBRz5d40c5ANLQlgcTceclbkxuY6xzg/s1600/2013-01-24_1120.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5_3M7WVdtbZA1PUaGZ3PO4A_orQ23LWENyAANz6rXqzDoHSAA78KQ6ow6f7vngcbDSDt6K4Xs6-Kvd4N-8vp1bXFpbOdn2L6s3YfcsUix6Y7UKBRz5d40c5ANLQlgcTceclbkxuY6xzg/s1600/2013-01-24_1120.png" /></a></div>
<div>
<br /></div>
<div>
That being said, <a href="https://github.com/mono/cxxi">Mono.Cxxi</a> is great stuff, check it out. But don't count on it for static AOT.</div>
<div>
<br /></div>
<h3>
Go SWIG</h3>
<div>
Miguel was, once again right. SWIG was the only sensible option. I've used <a href="http://www.swig.org/">SWIG</a> in the 90's for python (iirc), and it looks like the website hasn't left this era. But that's for the surface only. The tool is quite capable, is well suited for .NET and you can customise it to your liking. <a href="http://www.swig.org/Doc1.3/CSharp.html" target="_blank">There's even a tutorial</a> so I won't cover the basics. </div>
<blockquote class="tr_bq">
<span style="font-size: x-small;">pro-tip: on Mac, install swig with homebrew</span></blockquote>
<h4>
1. Get the DllImports right</h4>
<div>
The first thing to get right, is the DllImportAttribute for P/Invoke. It has to be like this</div>
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">[DllImport ("__Internal")]<br />public static extern void hello ();</span></blockquote>
You can instruct swig to do that by passing the -dllimport option<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">swig -c++ -csharp <span style="color: orange;">-dllimport __Internal</span></span></blockquote>
<h4>
2. Generate an obj-c++ wrapper</h4>
<div>
Swig generates glue code for you in a .cxx file. It turns out that, by simply renaming it to .mm, you get a perfectly valid Obj-C++ file. Create a new (<span style="font-family: Courier New, Courier, monospace;">Foo_wrapper</span>) library project with Xcode, link both that .mm file and the includes of the original library, and you'll easily get an iPhone-suited wrapper.<br />
<br />
<h4>
3. Getting rid of the AssemblyLoadExceptions</h4>
<div>
As is, the generated code compiles with smcs but crashes with an AssemblyLoadException as soon as you try to run it on the device or the simulator. That's because some SWIG generated helpers use reverse callbacks and those callbacks are usually <a href="http://docs.xamarin.com/ios/guides/advanced_topics/limitations#Reverse_Callbacks">JIT'ed by mono, which is not possible with static AOT</a>. The solution for this is then to tag the (autogenerated) <span style="font-family: Courier New, Courier, monospace;">SetPending*Exception()</span> and <span style="font-family: Courier New, Courier, monospace;">CreateString()</span> with <span style="font-family: Courier New, Courier, monospace;">[MonoPInvokeCallback]</span>. I do that by patching the file after the SWIG step.</div>
<div>
<br />
<script src="https://gist.github.com/4620130.js"></script></div>
<h4>
4. Putting all the pieces together</h4>
<div>
So here's a (simplified) Makefile that you can use to turn your SWIG foo.i interface file to a Foo.dll assembly wrapping and embedding your original <span style="font-family: Courier New, Courier, monospace;">libFoo.a</span> and the generated <span style="font-family: Courier New, Courier, monospace;">libFoo_wrapper.dll</span><br />
<br />
<script src="https://gist.github.com/4620250.js"></script></div>
<h4>
5. One last thing, set IsCxx = true</h4>
Don't forget to get your <span style="font-family: Courier New, Courier, monospace;">AssemblyInfo.cs</span> right, i.e. setting <span style="font-family: Courier New, Courier, monospace;">IsCxx</span> to true in your <span style="font-family: Courier New, Courier, monospace;">LinkWithAttribute</span>.<br />
<br />
<script src="https://gist.github.com/4620361.js"></script>
<br />
<h3>
Wrapping up</h3>
At this point, you should be all set and you should be able to use your native c++ library directly from within monotouch. Now you have to use your brain, mess with your <span style="font-family: Courier New, Courier, monospace;">foo.i</span> file and .NET-ify a bit your API.<br />
<br />
Would you have any issue with this, or any other binding or mobile development related stuff, contact me, I'm available for contracting.<br />
<br />
<br /></div>
Stephanehttp://www.blogger.com/profile/13725417672949898970noreply@blogger.com2tag:blogger.com,1999:blog-1907372157232963850.post-22938766519281554032010-01-13T15:36:00.006+01:002010-01-13T16:55:04.837+01:00Talk Teaser: Image processing with Mono.Simd<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5hH9_Fe-JINZHctv2ZAtk-N566gcNwr9JRXdrTz2U6ZDL4uql9rynpEzByNxx225X6cYV0t18dRz83WdAtpp8XSo94iPGhRSzb062nDFRcqOs5yJZWp1D2ZQpJPiCfE0sGG0ZxfxttP0/s1600-h/dsc_5125+%28Modified%29.jpg"><img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 320px; height: 214px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5hH9_Fe-JINZHctv2ZAtk-N566gcNwr9JRXdrTz2U6ZDL4uql9rynpEzByNxx225X6cYV0t18dRz83WdAtpp8XSo94iPGhRSzb062nDFRcqOs5yJZWp1D2ZQpJPiCfE0sGG0ZxfxttP0/s320/dsc_5125+%28Modified%29.jpg" alt="" id="BLOGGER_PHOTO_ID_5426234946422569906" border="0" /></a><span style="font-size:130%;">The facts:</span><br /><br />Processing time using gdk_pixbuf: <span style="font-weight: bold;">431ms</span><br />Same method ported to Mono.Simd: <span style="font-weight: bold;">66ms</span><br />That means roughly <span style="font-weight: bold;">6.5 times faster</span> !<br /><br /><span style="font-size:130%;">Some explanations:</span><br /><ul><li>The gdk-pixbuf is an unoptimized standard gdk operation (gtk+ 2.18.1), but I don't think a lot of them are optimized either using mmx or SSEx for this platform (x86-64). Feel free to prove me wrong here.</li><li>Times are averaged.</li><li>Loading and saving times aren't taken into account here, but both are using gdk_pixbuf operations.</li><li>The Mono.Simd method acts on vanilla pixbufs, and results are plain old usable pixbufs, not some kind of memory buffer or whatnot.<br /></li><li>The image attached to this post is not the result of the processing.</li></ul>This is only a teaser for the short talk I'll be giving at FOSDEM on Sunday Feb 7. Be there if you want to learn more, see the code, or question my sanity for doing this in Mono and not directly as a gdk-pixbuf patch.Stephanehttp://www.blogger.com/profile/13725417672949898970noreply@blogger.com8tag:blogger.com,1999:blog-1907372157232963850.post-31804205882466107882010-01-08T15:28:00.011+01:002010-01-11T16:09:58.001+01:00DeepzoomIt: a simpleminded DeepZoom composer<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2Kt247dZDbxdUk4WnkquRhS1jgeneinFyP2UftikYaqXqo_tl6UC46yHy_pEQ9ojI2R0anNU9no6v4f5oYUruACLZGsriarer1kLeI1v0JTyjDCNCs9feFpNW-2WGXnzRV90ZKV_iWlI/s1600-h/crayons.jpg"><img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 320px; height: 262px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2Kt247dZDbxdUk4WnkquRhS1jgeneinFyP2UftikYaqXqo_tl6UC46yHy_pEQ9ojI2R0anNU9no6v4f5oYUruACLZGsriarer1kLeI1v0JTyjDCNCs9feFpNW-2WGXnzRV90ZKV_iWlI/s320/crayons.jpg" alt="" id="BLOGGER_PHOTO_ID_5424377739405526178" border="0" /></a>Now that <a href="http://www.go-mono.com/moonlight/">Moonlight</a> supports DeepZoom for more than a year, it's about time to fill the blanks and allow one to create deepzoom images, even on linux.<br /><br /><span style="font-weight: bold;">DeepzoomIt</span> does just that.<br /><br />At least for the simple cases, i.e. no collection support and no selective resolution. But it generate files just right, as shown below (might not work on some planets) .<br /><br />DeepzoomIt uses gdk_pixbuf for image cropping, scaling, composing. And it shouldn't be sensible to the inability of gdk_pixbuf to scale images bigger than 65536px.<br /><br />The code is available on gitorious, use it if you like it: <a href="http://gitorious.org/deepzoomit">http://gitorious.org/deepzoomit</a>.<br /><br /><div id="silverlightControlHost"><br /> <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="500" height="300"><br /> <param name="source" value="http://files.reblochon.org/DeepzoomIt.xap"/><br /> <param name="background" value="white" /><br /><br /> <a href="http://go.microsoft.com/fwlink/?LinkID=115261" style="text-decoration: none;"><br /> <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none"/><br /> </a><br /> </object><br /> <iframe style='visibility:hidden;height:0;width:0;border:0px'></iframe><br /></div><br />[3159x2591 sized to viewport via DeepZoom. (shift-)Click to (un-)zoom. Drag to Pan]<br /><br />[Update 2010.01.11: replaced the pure xaml viewer by a managed one. Pan+Zoom works.]Stephanehttp://www.blogger.com/profile/13725417672949898970noreply@blogger.com13tag:blogger.com,1999:blog-1907372157232963850.post-47356704208655694012009-12-03T16:30:00.000+01:002009-12-03T16:33:26.713+01:00Mono devroom @ FOSDEM 2010<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhs2Dm7BFUsKD4gXd3fo-IbDYy3ZSXo_SJxAqP5zwEyBl8EG3EokEAiPWrlF3D6wpd2Qhh3ZaKrP462P5tEG8PZ1ufUlqtN0Q8ragn_ZpPqNNA9NmpVEQ2oK0KLxCRi22VmAHC_sdG-aoE/s1600-h/dsc_4842+%28Modified%29.jpg"><img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 292px; height: 320px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhs2Dm7BFUsKD4gXd3fo-IbDYy3ZSXo_SJxAqP5zwEyBl8EG3EokEAiPWrlF3D6wpd2Qhh3ZaKrP462P5tEG8PZ1ufUlqtN0Q8ragn_ZpPqNNA9NmpVEQ2oK0KLxCRi22VmAHC_sdG-aoE/s320/dsc_4842+%28Modified%29.jpg" alt="" id="BLOGGER_PHOTO_ID_5411029652195601378" border="0" /></a>Mono got a room at <a href="http://fosdem.org/2010/">FOSDEM2010</a> in Brussels, so we won't have to do that in the hallway this year !<br /><br />Want to speak about something fun you did with mono ? <a href="http://spreadsheets.google.com/viewform?hl=en_GB&formkey=dGlRMUJfbzVjaUZOSlpYeHFOS19ZdFE6MA">Propose a talk</a>. Using mono on your servers saved your company from bankrupt in 200[89] ? <a href="http://spreadsheets.google.com/viewform?hl=en_GB&formkey=dGlRMUJfbzVjaUZOSlpYeHFOS19ZdFE6MA">Talk about it too</a>. You are a passionate mono hacker and want to spread the word about what we'll got in the upcoming version ? <a href="http://spreadsheets.google.com/viewform?hl=en_GB&formkey=dGlRMUJfbzVjaUZOSlpYeHFOS19ZdFE6MA">You know the link</a>.<br /><br />And for everyone else, eager to learn about it, to discuss it, join on Sunday Feb 7. You're all welcome.<br /><br /><span style="font-weight: bold;font-size:85%;" >Note: be quick, the deadline for the cfp is around Dec 20.</span>Stephanehttp://www.blogger.com/profile/13725417672949898970noreply@blogger.com0tag:blogger.com,1999:blog-1907372157232963850.post-25257354427221618082009-11-23T16:07:00.001+01:002009-11-23T16:55:31.770+01:00Unleash your (F-Spot) toolbox<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhV0_1SVK-SUF2C8pRb30rGqJd9ECoAEPmTdEuQ5uTOjtJhROrpelf7QdgqeL_sIZdN6Y0u-DTR9ppimZdRWbINdGwU-PXrJK1a_kt6AJmZHoKHEeauLorte9mru9hprvXeCAAPi9ZqxvE/s1600/dsc_4773+%28Modified+in+GIMP%29.jpg"><img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 320px; height: 214px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhV0_1SVK-SUF2C8pRb30rGqJd9ECoAEPmTdEuQ5uTOjtJhROrpelf7QdgqeL_sIZdN6Y0u-DTR9ppimZdRWbINdGwU-PXrJK1a_kt6AJmZHoKHEeauLorte9mru9hprvXeCAAPi9ZqxvE/s320/dsc_4773+%28Modified+in+GIMP%29.jpg" alt="" id="BLOGGER_PHOTO_ID_5407306510940104738" border="0" /></a><a href="http://twitter.com/mpt/status/5829411979">Rumor has it</a> that, during latest UDS, Ubuntu planned to drop Gimp from the default distro and the LiveCD. I won't comment this decision as 1) I have no clue if that's a rumor or more, 2) it was already commented too much, 3) I'm not a whiner, 4) there's a rationale behind that decision and I think I understand it, 5) the full Gimp is only one apt-get away.<br /><br />But some were concerned about the lack of basic image editing. Enters <a href="http://f-spot.org/">F-Spot</a>, the loved Photo Manager and his little brother, the --view mode. The --view mode is a standalone application, which, on top of F-spot loaders and widgets, provide a simple (ala eog) image viewer, which only view the images, and let you browse the metadata. This is it. Or was it 1h30 ago. With very few code, I plugged the main F-Spot editors inside the single view mode. And that worked quite well !<br /><br />Of course, F-Spot editors are nowhere close to Gimp's, and don't even aim too. But they cover 90% of your daily usage and are (probably) simpler to use than Gimp. And even more, you can write (read contribute) some additional ones in very few lines of code. e.g. the <a href="http://blog.reblochon.org/2009/09/news-from-f-spotters.html">BlackAndWhite extension</a> is 120 lines long with the UI, despite behing optimized to run on Simd !<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd3x69r_vtGiAFNDju43tkiFq2KcwbovUKd30vv62IzEBzS4NOvERzdxaES9m5fwK3pbwjTk0GPHhLLpmP6H8aTdsiLGY5bcpwO9Q3MNslr4K8K0LVC67fYnp3rPGL2DA9Kh67jGMl_Cw/s1600/Screenshot-F-Spot+View.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 309px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd3x69r_vtGiAFNDju43tkiFq2KcwbovUKd30vv62IzEBzS4NOvERzdxaES9m5fwK3pbwjTk0GPHhLLpmP6H8aTdsiLGY5bcpwO9Q3MNslr4K8K0LVC67fYnp3rPGL2DA9Kh67jGMl_Cw/s400/Screenshot-F-Spot+View.png" alt="" id="BLOGGER_PHOTO_ID_5407316186320127570" border="0" /></a><br /><br />Expect this to be available soon on git, and a bit later in a release !Stephanehttp://www.blogger.com/profile/13725417672949898970noreply@blogger.com19tag:blogger.com,1999:blog-1907372157232963850.post-12515490009416294932009-11-06T14:27:00.002+01:002009-11-06T15:04:42.764+01:00Multiple branches and translations<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibBLl_zbuZVUUGPIFoExY7ju_Xdz3vbW1Vp1QhbimwUzrR9Xk3KGGfwemmBZ0daHm0sRn8QNj3zppqvWUmSnQonjYfUP8_VEgV8dTmKSEyvsxvnGASImnGNC6m10631CqQ5M3tWXFkUwQ/s1600-h/dsc_4756+%28Modified+%282%29%29.jpg"><img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 174px; height: 320px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibBLl_zbuZVUUGPIFoExY7ju_Xdz3vbW1Vp1QhbimwUzrR9Xk3KGGfwemmBZ0daHm0sRn8QNj3zppqvWUmSnQonjYfUP8_VEgV8dTmKSEyvsxvnGASImnGNC6m10631CqQ5M3tWXFkUwQ/s320/dsc_4756+%28Modified+%282%29%29.jpg" alt="" id="BLOGGER_PHOTO_ID_5400984136198960066" border="0" /></a>Fellow Package Maintainers,<br /><br />How are you dealing with this ?<br /><br />I guess <a href="http://f-spot.org">f-spot</a> is not the only project maintaining multiple parallel branches, a <span style="font-weight: bold;">STABLE</span> one, from which the releases and bugfix releases are created, and a <span style="font-weight: bold;">master</span>, open for business, new stuffs, and experimentations.<br /><br />When we need to correct something on the <span style="font-weight: bold;">STABLE</span> branch, we push a new commit over there, then merge the <span style="font-weight: bold;">STABLE</span> back to <span style="font-weight: bold;">master</span> so it gets the same fixes. That works fine.<br /><br />But it gets harder with translation commits. Most of the (awesome) translators (well, all except of one) translates the <span style="font-weight: bold;">master</span> and commits right there. Then, when it's time to release, I either ignore those translations (and that's seriously annoying for translators who pushed soem work in the .po), or I blindly backport (cherry-pick) the translations back to the <span style="font-weight: bold;">STABLE</span> branch and hope that no strings was removed in <span style="font-weight: bold;">master</span>'s code<span style="font-weight: bold;"></span>. Then I merge the <span style="font-weight: bold;">STABLE</span> back to <span style="font-weight: bold;">master</span>. Both solutions are seriously suboptimal. Really.<br /><br />I know how this problem is "solved" in most of the GNOME projects by putting deadlines and code freezes, and string freezes, but I guess we're not the only project around with this kind of issue.<br /><br />The <span style="font-style: italic;">ideal</span> workflow would be to have the translators (hey guys) aware of the <span style="font-weight: bold;">STABLE</span> branch, make them translate that branch, have them merge it back to <span style="font-weight: bold;">master</span>, and then, optionally, translate the missing/changed strings and commit that to <span style="font-weight: bold;">master</span>. I said <span style="font-style: italic;">ideal</span>, cause I'm NOT gonna ask any translator to understand and follow this, be able to maually merge if something goes wrong, etc...<br /><br />Translators (did I say thanks for your job lately) are already doing an ant job, most of them with no tools but a text editor, and we can't really add any pain to the process.<br /><br />So, what are you doing in that case. How could we improve the process ?<br /><br />Comments are open.Stephanehttp://www.blogger.com/profile/13725417672949898970noreply@blogger.com4tag:blogger.com,1999:blog-1907372157232963850.post-72114165815220587472009-10-31T13:49:00.000+01:002009-10-31T13:51:36.840+01:00Mono-ifying Gnome3, one dependency at a time<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiblCdzrm9_DijCE2R_p5xpD6-vX2T7klu154rnKguR5FHp_Ca82_Dl_1XCrQ9OApWWfTLIPubJwbywE16Wa8Y9kC5MtX-HbI1qtEPq-oaLmpzSjiR2eH-cBxggnZ3In5hixUu8nna2ws0/s1600-h/dsc_4122.jpg"><img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 320px; height: 214px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiblCdzrm9_DijCE2R_p5xpD6-vX2T7klu154rnKguR5FHp_Ca82_Dl_1XCrQ9OApWWfTLIPubJwbywE16Wa8Y9kC5MtX-HbI1qtEPq-oaLmpzSjiR2eH-cBxggnZ3In5hixUu8nna2ws0/s320/dsc_4122.jpg" alt="" id="BLOGGER_PHOTO_ID_5398422419206049378" border="0" /></a>2 quick announcements:<br /><br /><a style="font-weight: bold;" href="http://live.gnome.org/LibUnique">libunique</a> now has a managed binding, <span style="font-weight: bold;">Unique#</span>. As the mapping is already feature complete and API stable, the code is tagged 1.0.0. It's simple, it's as easy and obvious to use as the native libunique, it doesn't have funky dependency (except, well, for libunique 1.0.0), it installs itself in the GAC...<br /><br />The code is hosted on gitorious <a href="http://gitorious.org/unique-sharp/unique-sharp">http://gitorious.org/unique-sharp/unique-sharp</a> and patches are welcome. There's no tarball so far, but if you need one, ask and you might receive.<br /><br /><a style="font-weight: bold;" href="http://f-spot.org/">F-Spot</a> got yet another bugfix release (0.6.1.4) I worked on during the weekend, fixing an X issue on some screens. Unfortunately, the Karmic release of Ubuntu (congrats guys) unleashed a new horde of avid testers, and they were able to find an <a href="https://bugzilla.gnome.org/show_bug.cgi?id=600032">issue</a> in the --view mode (the same issue, for the same widget, was reported for the facebook exporter too). I'll look at it this weekend, in the meantime the workaround is to run f-spot --view with GDK_NATIVE_WINDOWS=true.<br /><br />[Update 2009/10/31: bug fixed]Stephanehttp://www.blogger.com/profile/13725417672949898970noreply@blogger.com6tag:blogger.com,1999:blog-1907372157232963850.post-87520185068790464812009-10-29T11:16:00.003+01:002009-10-29T12:50:58.524+01:00Every now and then, it's time to...<span style="font-size:130%;">Regenerate a new keypair</span><br /><br />The old keypair served me well during those past 8 years, but I managed to screw it up in the process of upgrading to opensuse 11.2 rc1. Here's the new public part:<br /><br /><pre><br />-----BEGIN PGP PUBLIC KEY BLOCK-----<br />Version: GnuPG v2.0.12 (GNU/Linux)<br /><br />mQENBErpajsBCADVpFuXevFtqwT44k5b3fAzWLlLKm0JkawrtFir/lpkZp4SMFrn<br />ZiQ+4I5OOcptmpQfZ6oLqE1P2pGUsl9H0V9CxI9NOK+z2dQBh36ccPPLXhjtG/wO<br />rIymJJ0UBVRjGUL+1IhGXI3u/BVY1yzEahCUd2gf3BpJkE8COvB6ewL2KPvCfery<br />vx5Ot0xAqfKVCAtJ8DEVeeVW+//s++DzdiTMqbRzMApM44rT/nd3ebhx/lEb8Opo<br />143JZKqyrlJ18f0B6CwVjufvnwqb5fvAA9TWRZ3qfbSvRQcRvhaSnAjR1WiDdmhO<br />FdJJwFLDfcx9vz8snCoB5aqjLXq+AncuhnTtABEBAAG0KVN0ZXBoYW5lIERlbGNy<br />b2l4IDxzdGVwaGFuZUBkZWxjcm9peC5vcmc+iQE2BBMBAgAgBQJK6Wo7AhsDBgsJ<br />CAcDAgQVAggDBBYCAwECHgECF4AACgkQYrBLwhj7hs4PGQgAzX4/Xpbz/g5LP6LU<br />huNi3mabC/SUfQ/jHfO+0pHpF2jTxaUF+eCdEC86FOZubtTHtvSN9tFBWgazvDaW<br />HvFBQgKBfjaWUHOXXeMkPsWhOkXIqaEE2kYHuqLrijDNgtTq/So1PcPIpAJsY1rr<br />No++7xKvC9/usEDlnrcz8D7jyyZN/6FGFMZ2YlxCq2qV7+6yJUK4XpLdrLIYChGW<br />IlLHL4jrHHwnEDtSg7aTMGK+gy4U2ha/rzcEtOS5ec1Tx3MrkWc2Z3BGHZDDTtJd<br />xeE85GsxsYWNWgt1XzwuHrvK7yPq3Udvgthqpi//VqXfA5S98edJQNc8BXIBYZ7S<br />90FB4rkBDQRK6Wo7AQgAr5exsNtPs3EW901frwoVFlZLSwWYJDESUJLK7CLS+B+I<br />fIwPWTP/v+VkaJqJNdjZkXx9d78XFjG0nb/o4xo2m7moCr/+7HnkE/7CdXmepzgU<br />oZ9EK1PWyPARYVD6JWAG0NQ/SzcEKqJyo+SCfNgVEdq/ls28zXVM0dzBRjOV5sQg<br />+fksv91d3cPo3+RKpdHfxAUTaW11nsgXiWofx6wbKvKQl2DSjB+8I+YnfAUaRtJq<br />2BfYHAl8eXvdMhnwkFNIpMQQ8T5phEHJEcp2k6D03HBIwWEkcIG6OLu3g2XGgC8p<br />z7o8ktRhUre6dEFDCaX2gYMDKviPikqOOlGvNKRgcQARAQABiQEfBBgBAgAJBQJK<br />6Wo7AhsMAAoJEGKwS8IY+4bOE7cH+wcnAxDYsnnT8NakDqflpzFgtD2r1SLE1J1s<br />aKk0XXtSSQWQSpxC7YEm9W37SyCBoajPoganWq8FT28VrRV2OqTi88QFOezvgZIW<br />VoRJHlrtXj3qvdSkF7zImOzCJpN3bKsp+SSO7Kp9KJ3ypGk7ozkgzArB45C6Ydnx<br />lxcKuoGpb/lr89c/COq4vsaRw4DaXwYbruFITNvRQyq9rZnnYzLnVvZMvmFWU9JI<br />NCGa5zJbXeNxBUNYpGA3GjaS5ACeVKyHVIJCG4rlxVW/w4AcrHVv+GqIXcuQWuKN<br />Io2gaZLUPV38CoeKCWWedvTFtYTqHOcHW9iGofr2kEKbz6kXCQA=<br />=QzP8<br />-----END PGP PUBLIC KEY BLOCK-----<br /></pre>Stephanehttp://www.blogger.com/profile/13725417672949898970noreply@blogger.comtag:blogger.com,1999:blog-1907372157232963850.post-49523311201420692962009-09-28T21:38:00.008+02:002009-11-06T17:29:34.731+01:00Fixes by pack of 12<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBySKD_zcMQpt5GeZrMyYzeJiF8fA6BNCJSzd3q22jP3nEYqfeiyyJNdXTb-JzjHu1n5ALWJ-DSxujbmETsxDAdRf8JAcl_tt-LACf8Yzk-o2AAMjFn4btKv3kq70rIel24Fa_WTT9R34/s1600-h/img_3098.jpg"><img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 320px; height: 214px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBySKD_zcMQpt5GeZrMyYzeJiF8fA6BNCJSzd3q22jP3nEYqfeiyyJNdXTb-JzjHu1n5ALWJ-DSxujbmETsxDAdRf8JAcl_tt-LACf8Yzk-o2AAMjFn4btKv3kq70rIel24Fa_WTT9R34/s320/img_3098.jpg" alt="" id="BLOGGER_PHOTO_ID_5386605332642064642" border="0" /></a>Important things first, just know that Ruben is no longer AWOL. He's even back to hacking mode, and working, together with Tigger, at adding image metadata support for images to taglib-sharp.<br /><br />Now to the futile, I just released <span style="font-weight: bold;">F-Spot 0.6.1.3</span> a few minutes ago. The main purpose of it was to fix the slideshow mode on gtk+ 2.18 (which we did) and as I was at releasing, I applied some pending patches from bugzilla, wrote some myself, and backported translations from master.<br /><br />The change in the importing code is worth noticing. It no longer imports the files first to memory before writing them to disk. It's quite helpful now that most cameras can create video files bigger enough to fill your machine memory in less than a few minutes (at high bitrate, on HD resolution). It's only available if you have libgphoto2 >= 2.4 and doesn't work with the directory driver (used for memory cards e.g.). Marcus is working on a fix in gphoto2, so stay tuned.<br /><br />If you ask about the screensaver, it still doesn't work with gtk+ 2.18 but works fine with gtk+ master, and will still work just fine with gtk+ 2.18.1 when it goes out.<br /><br />That's it. Download it, build it, package it, enjoy it!Stephanehttp://www.blogger.com/profile/13725417672949898970noreply@blogger.com0tag:blogger.com,1999:blog-1907372157232963850.post-24024338611246500972009-09-16T22:12:00.009+02:002009-11-23T16:12:00.779+01:00News from the F-Spotters<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSGiF1BKZ_Pwhvoy922BeJZhDrFWCoOZUztHp898Vz6j95d5zmNfSnheSrmbDXSJYVJST8jLgatK6fGOfBpdHVSdf1pnqyI3Q3i287j2qp6UtNhXjVd32CPU_cK7SsG4V1e2IStMvM6SI/s1600-h/dsc_9253+%28Modified%29.jpg"><img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 320px; height: 256px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSGiF1BKZ_Pwhvoy922BeJZhDrFWCoOZUztHp898Vz6j95d5zmNfSnheSrmbDXSJYVJST8jLgatK6fGOfBpdHVSdf1pnqyI3Q3i287j2qp6UtNhXjVd32CPU_cK7SsG4V1e2IStMvM6SI/s320/dsc_9253+%28Modified%29.jpg" alt="" id="BLOGGER_PHOTO_ID_5382161914680979058" border="0" /></a><br />Some news, in no particular order:<br /><br /><span style="font-weight: bold;">F-Spot 0.6.1.2</span> was released a couple of minutes ago. It fixes db upgrade for the people who went in holidays in the far future. Now F-Spot can update a db with photos taken (or reported to be) after 2038. It also fixes a crash while running on gtk+ 2.14.<br /><br />The <a href="http://blog.azib.net/2009/08/announcing-f-spot-live-web-gallery.html"><span style="font-weight: bold;">LiveWebGallery</span></a> extension is now merged into the main tree, and installable, from the Manage Extension dialog, on any F-spot > 0.6. The extension crashing on gtk+2.14 is part of the past too.<br /><br /><span style="font-weight: bold;">Ruben</span> is MIA. Last time we heard from him, he was "in a park near a pond near a museum".<br /><br />A new extension, allowing finer control over the <span style="font-weight: bold;">BlackAndWhite conversion</span> process is coming soon. It leverages the expensive CPU you paid big bucks for via <a href="http://tirania.org/blog/archive/2008/Nov-03.html">Mono.Simd</a>. Mandatory screenshot: <a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMIKZQYWUaH0Wwi-JET0MLD-iwdedt3HpEv-I0pW3HdjM9zsljTGRxFsDHiZ7MmHvIIZnzw_F7LE393JcSEscvEed_zzVaqC6kre4lUZhOmYoQbPu3MOp4_Wxs-_ajZR4qHGEsKtz60ks/s1600-h/Screenshot-F-Spot-3.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 313px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMIKZQYWUaH0Wwi-JET0MLD-iwdedt3HpEv-I0pW3HdjM9zsljTGRxFsDHiZ7MmHvIIZnzw_F7LE393JcSEscvEed_zzVaqC6kre4lUZhOmYoQbPu3MOp4_Wxs-_ajZR4qHGEsKtz60ks/s400/Screenshot-F-Spot-3.png" alt="" id="BLOGGER_PHOTO_ID_5382164474137799010" border="0" /></a><br />That's it for today.Stephanehttp://www.blogger.com/profile/13725417672949898970noreply@blogger.com7tag:blogger.com,1999:blog-1907372157232963850.post-5816832692476667732009-08-28T11:08:00.008+02:002009-10-26T11:43:01.256+01:00GtkBuilder on IronPython<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKu7ZZO0_YSXCZXq1RIhg9qbkYbl0203k_gS7ODKDXQOa-fA0qpamC8mVY_Df07ykdFg1HN8-FrS81YwaN0fIj8SGAA-hg69noKt35HCN_w5-xCryNk99NbKpKM6PDTZHko2do75fcVLg/s1600-h/dsc_3942+%28Modified%29.jpg"><img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 194px; height: 146px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKu7ZZO0_YSXCZXq1RIhg9qbkYbl0203k_gS7ODKDXQOa-fA0qpamC8mVY_Df07ykdFg1HN8-FrS81YwaN0fIj8SGAA-hg69noKt35HCN_w5-xCryNk99NbKpKM6PDTZHko2do75fcVLg/s320/dsc_3942+%28Modified%29.jpg" alt="" id="BLOGGER_PHOTO_ID_5374939143473861506" border="0" /></a>Someone asked me if I could add the missing parts of GtkBuilder in <a href="http://gitorious.org/gtk-sharp-beans">Gtk#Beans</a> so he could use it with <a href="http://ironpython.codeplex.com/">IronPython</a> on mono.<br /><br />Hey, it looks there's no missing parts ! It all works fine since day one. Here's the the trick:<br /><pre><br />import clr<br />clr.AddReference('glib-sharp')<br />clr.AddReference('gtk-sharp')<br />clr.AddReference('gtk-sharp-beans')<br />import Gtk<br />import GLib<br />import GtkBeans<br />import System.IO<br /><br />def PyBuilderAutoconnect(builder, target):<br />def _connect(builder, object, signal_name, handler_name, connect_object, flags):<br /> name = ''.join([frag.title() for frag in signal_name.split('_')])<br /> event = getattr(object, name)<br /> event += getattr(target, handler_name)<br /><br />for object in builder.Objects:<br /> setattr(target, object.Name, object)<br />builder.ConnectSignalsFull (_connect)<br /><br />class Application:<br />def __init__(self):<br /> builder = GtkBeans.Builder (System.IO.FileStream ('ui.ui', System.IO.FileMode.Open))<br /> #use this ctor if you don't like FileStream<br /> #builder = GtkBeans.Builder ()<br /> #builder.AddFromFile ('./ui.ui')<br /><br /> PyBuilderAutoconnect (builder, self)<br /> self.window1.ShowAll ()<br /><br />def onbuttonclicked(self, o, args):<br /> Gtk.Application.Quit()<br /><br />Gtk.Application.Init ()<br />app = Application ()<br />Gtk.Application.Run ()<br /></pre>Now your IronPython skills are ready to rock Gnome3!Stephanehttp://www.blogger.com/profile/13725417672949898970noreply@blogger.com1tag:blogger.com,1999:blog-1907372157232963850.post-89368678467298510372009-08-27T15:56:00.007+02:002009-10-26T11:43:59.353+01:00AwesometasticI woke up this morning with an awesometastic merge request from <a href="http://blog.azib.net/">Anton Keks</a>. During the night (or was it already started weeks ago ?) he wrote a LiveWebGallery extension for <a href="http://f-spot.org/">F-Spot</a>. It means that you can, using a web browser, see the whole (or only parts of) photo collection of someone else in your local network.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhd2sgXDRN9uRnOEGIYlF_mgsJUY77LEFGrumd43Np246aHMizLpDzSdre8yn534t43PKtu118-5y6Epgy8RntfLS7fi__34qZ5xmjOH55PNU6hJN6SqDUAfUWLz1fBWVVNmFLXirfHyzk/s1600-h/LiveWebGallery.jpg"><img style="cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhd2sgXDRN9uRnOEGIYlF_mgsJUY77LEFGrumd43Np246aHMizLpDzSdre8yn534t43PKtu118-5y6Epgy8RntfLS7fi__34qZ5xmjOH55PNU6hJN6SqDUAfUWLz1fBWVVNmFLXirfHyzk/s400/LiveWebGallery.jpg" alt="Mandatory Screenshot" id="BLOGGER_PHOTO_ID_5374643253311443970" border="0" /></a><br /><br />The HTML/js UI is pretty slick even !<br /><br />The code is not merged yet, but I packaged the extension and it's now installable from within F-Spot (> 0.6.0.0) from the "Extension Manager" dialog.<br /><br />More details can be found on <a href="http://blog.azib.net/2009/08/announcing-f-spot-live-web-gallery.html">Anton's blog</a>.<br /><br /><span style="font-weight: bold;">[Update 2009/09/15. The code is now merged]</span>Stephanehttp://www.blogger.com/profile/13725417672949898970noreply@blogger.com0tag:blogger.com,1999:blog-1907372157232963850.post-22550530152368326092009-08-25T23:46:00.006+02:002009-10-26T11:41:45.295+01:00It's gonna be legendarywait for it... <a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxEIVfaTX5_jh8MYYJvrM4ocmO_Na7RHfAR9fQe1cHe5vmn71r0dNvJDWXOAgK4gRMbMxqggXFsUEAhZ9hv-1mMZQ_Jnr7pvyu4XR2NFkFXg5m-ovmAOWwtLaLlekdGtmTwPVd-5DMp88/s1600-h/dsc_4086+%28Modified%29.jpg"><img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 319px; height: 320px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxEIVfaTX5_jh8MYYJvrM4ocmO_Na7RHfAR9fQe1cHe5vmn71r0dNvJDWXOAgK4gRMbMxqggXFsUEAhZ9hv-1mMZQ_Jnr7pvyu4XR2NFkFXg5m-ovmAOWwtLaLlekdGtmTwPVd-5DMp88/s320/dsc_4086+%28Modified%29.jpg" alt="" id="BLOGGER_PHOTO_ID_5374021529843588642" border="0" /></a><span style="font-weight: bold;">F-Spot 0.6.1.0</span> is out!<br /><br />This one is coming quite soon after 0.6, and contains only fixes, cleanups and translation updates.<br /><br />It aims to be a packager friendly release, as it drops some bundled code, some dependencies, a few megs of code, and more than a megabyte of installed size !<br /><br />So, if you were using or packaging 0.6.0.0, jump in now, enjoy the .1.<br /><br />[Update: I pushed 0.6.1.1 to avoid a reported build issue]Stephanehttp://www.blogger.com/profile/13725417672949898970noreply@blogger.com8tag:blogger.com,1999:blog-1907372157232963850.post-89194492944454344952009-08-07T21:51:00.004+02:002009-10-26T11:41:39.076+01:00Pit Stop<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZiGy2lN5_CYZsYSzXk8P5bIIcEsX1WQtiAgfbH1j3QYmMN94xF9rspIw-0oLdNO7G3EaCQRKkKICQgi94YUysEmqJqojyih_wgAprAprN4KinEypaYo6R_G5eiHDA7kKVjgFR5OvlVzA/s1600-h/dsc_3768+%28Modified%29.jpg"><img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 320px; height: 240px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZiGy2lN5_CYZsYSzXk8P5bIIcEsX1WQtiAgfbH1j3QYmMN94xF9rspIw-0oLdNO7G3EaCQRKkKICQgi94YUysEmqJqojyih_wgAprAprN4KinEypaYo6R_G5eiHDA7kKVjgFR5OvlVzA/s320/dsc_3768+%28Modified%29.jpg" alt="" id="BLOGGER_PHOTO_ID_5367312707687835090" border="0" /></a>On our way to F-Spot 1.0, we slowed our well oiled machine to change the tires, fill the tank and do a complete check against the various regressions we might have added while packing tons of new features and changes since the 0.5.x releases.<br /><br />The truck is now ok and ready to ride to the next milestone. Check 0.6.0 in order to make your own opinion.<br /><br />Neither this short post nor the NEWS file reflects the really hard work pushed by our contributors, translators and designers, but rescanning the git log this evening reminded me how hard we all worked for this. Thanks guys.<br /><br /><a href="http://ftp.gnome.org/pub/GNOME/sources/f-spot/0.6">Get it here</a>.Stephanehttp://www.blogger.com/profile/13725417672949898970noreply@blogger.com2tag:blogger.com,1999:blog-1907372157232963850.post-6980598306088972722009-06-24T13:16:00.000+02:002009-06-24T13:20:07.748+02:00Report on F-Spot loading times<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvkPDI5H5hNY1QZAJT1s0aIqw8ex2_Du7PH5LobAOp67qTjWX_VNHFwV5CaKS6m8PkHB540Iz806FJGsCUVNN3HfENExLnqLOsW2En-W3EtKYkNq8XDdkI4XvYiMZhLrpGqUnSs6CNnPM/s1600-h/late.jpg"><img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 293px; height: 320px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvkPDI5H5hNY1QZAJT1s0aIqw8ex2_Du7PH5LobAOp67qTjWX_VNHFwV5CaKS6m8PkHB540Iz806FJGsCUVNN3HfENExLnqLOsW2En-W3EtKYkNq8XDdkI4XvYiMZhLrpGqUnSs6CNnPM/s320/late.jpg" alt="" id="BLOGGER_PHOTO_ID_5350826013659890706" border="0" /></a><br />before: (on 0.5.0.3, averaged loading times on the first 10 items of my collection)<br /><span style="font-family:courier new;">Loading image took 1.292241s</span><br /><br />after: (current master, averaged on the same 10 items)<br /><span style="font-family:courier new;">Loading image took 0.518812s</span><br /><br /><br /><br />[UPDATE] Yes, that's on a dual core machine (Intel(R) Core(TM)2 Duo CPU L7500 @ 1.60GHz).Stephanehttp://www.blogger.com/profile/13725417672949898970noreply@blogger.com9