Synergy Advance progress report
-
Greg Hurrell
I am pleased to report that tonight I hit the first major milestone in the Synergy Advance development roadmap.
Up until now I have been working on application design and a framework called WOBase that is common to Synergy Advance and other future Wincent apps, such as GetSmart Pro. (WinHex, which is already out, is the first product using the framework to be released to the public.)
Tonight I started work on the first code specific to Synergy Advance (ie. custom code, that won't be reusable in any other app). This means I'm on the road to the first public beta release (version 0.1). Please, don't ask for predictions about a release date, because it's still too early to say. But it is good to know that progress is being made...
-
Krypton
I look forward to seeing what this app offers
-
Greg Hurrell
Out of interest, as of right now, the Synergy Advance codebase contains 5,286 lines of code. Thought I'd post this here because it will be interesting to see the rate it grows over the coming months...
(To give you some idea of what this means, this compares with the 40,000 to 50,000 that are in Synergy.)
-
Krypton
Hmmmm that's a lot of lines.... or not very many compared to Office.
Might we see some screenshots as things progress?
-
Greg Hurrell
Quote: Might we see some screenshots as things progress?
I don't have any plans to post screenshots, because I'll be releasing early (at version 0.1) so you'll be able to see it for yourself.
One reason why I will be remaining tight-lipped about forthcoming features is that I am aware of how much copying occurs in the industry. It's a somewhat painful lesson that I learnt with Synergy: that every good idea I had would be immediately copied by a number of competitors. So, basically, I have no intention of talking about future features because it will only give these people a "to do" list to start working on. I'd rather they be totally surprised when the feature comes to market and then they're forced to play "catch up" and implement their own copy if they want to continue to be seen to be "innovating".
I've come to realise that one of the most valuable resources a software outfit can have is ideas, so I'll be doing my best to protect that resource from here on in.
So that's why I am happy to let people know that development on Synergy Advance is occurring, but that I am not making specific comments about what its capabilities will be. All I can do right now is make vagues statements along the lines of, "Synergy Advance will be able to do all the things that, for technical reasons, are just not practical to implement in Synergy". There will be some feature overlap between the two programs, but as Synergy Advance development continues the gap is only going to widen. Hopefully you'll agree with me that it'll be worth the wait.
-
Krypton
As long as there's a playlist menu generated from the xml file I shall be very happy
Although it may be bad for you, having plagiarising competitors is good for us (users) as it forces you to think about better features.
-
Greg Hurrell
Quote: Although it may be bad for you, having plagiarising competitors is good for us (users) as it forces you to think about better features.
Unfortunately, I've never had any trouble coming up with ideas; it's finding the time to implement them that's the problem...
But making good progress right now: total after another day's work: 5,781 lines of code in WOBase, and 598 in the Synergy Advance-specific stuff.
-
Greg Hurrell
Almost done for the day (12:10 AM): 6,120 framework lines, 747 Synergy Advance-specific lines.
updated multi-threading locking mechanisms to use the new Objective-C @synchronized directive where appropriate instead of the old NSLock class. updated and expanded accessor macros, now supplying a "fast", "default", and "thread-safe" variants. wrote up plenty of notes, documentation, and did quite a bit of research. secret stuff...
-
Greg Hurrell
Went away for the day on Sunday, and ended up getting back after lunchtime today (Monday), so didn't get a lot of coding done. I did, however, have an idea or two while I was away, and I'm in the process of implementing it now.
I've made a new NSObject subclass and inserted it into the object hierarchy throughout the entire project so that every class is a direct or eventual descendent of my new (WOObject) class. I'm in the process of adding all sorts of nifty stuff in this class which will enable me to elegantly and transparently do some handy memory debugging and unit testing. This complements and extends all the unit testing stuff I wrote the other day.
[Remember how some of the less well-informed Mac enthusiasts used to speculate that the reason why certain versions of Mac OS X were so slow was that Apple had "forgotten to turn off the debug code"... well, the debug code I am talking about here is definitely the sort of code that could slow your app down if you shipped it with it all "turned on"; but the flip side of the coin is that when it is "turned off" it is completely omitted from the project and doesn't add any baggage at all. And I have no intention of "forgetting to turn it off"...]
At the end of the day this kind of thing doesn't translate directly into a shiny button in the UI that the user can press and say, "Wow!", but it does make it easier to produce reliable, bug-free, well-tested, robust code. And a little bit of time spent laying this groundwork now could pay off greatly later on in terms of time saved, time that would otherwise have been spent chasing bugs.
-
Greg Hurrell
Work continues... just finished setting up automated build numbering which embeds a build number and a time stamp in the build in the WOBase framework; this will come in handy when it comes time to do troubleshooting or bug reporting. As in the past, achieving this involved battling with both AppleScript and sed, neither of which I am very enamoured with (especially in the case of sed), but this time I actually managed to bend them to my will without any swearing. This must be a first for me.
Other low level stuff I've been working on lately includes retain/release, alloc/dealloc tracking (once again for debugging), more unit testing stuff, some useful extensions to NSDictionary, and some macros which should enable me to churn out quicker code with less scope for making clumsy typing errors.
High level stuff I've been working on, and will continue with tomorrow, mostly revolves around the preferences system. The new system will allow me to cram a lot more options in, and I'll be using the same basis in GetSmart Pro as well.
Next up: a custom table view which will allow me to really pack in the options under the "Advanced" section without losing readability and clearness.
-
Greg Hurrell
Lots of ground covered on the preferences system today; making it as close as I can to Apple's own System Preferences. Testing, testing, testing... and much to my delight everything works. Along the way made some more macros that should save me a bit of time and make it easier to write more robust code.
-
Greg Hurrell
Preferences window now remembers its position across runs, also handles the fact that the window size can vary depending on which prefPane is being displayed; more work on the "Show all" view; and the system now handles the case where only a single pane is provided.
-
Greg Hurrell
Worked on various things today to make the preferences window behave more like Apple's System Preferences: draggable buttons for the "Show all" view; when dragging, both the labels and the button graphics move together; creating NSImages from NSViews, and more... basically just being perfectionistic.
This is one job I want to do only once, and do it right. It makes sense to do it well because I should be able to use it with every other product I release in the future.
-
Greg Hurrell
"Show all" view now available alphabetically, or organized by categories like Apple's System Preferences. Switching between views implemented, and I am about to add a caching mechanism. Like Apple's System Preferences, launch time is kept to a minimum because panes are only loaded when the user clicks on them; but loaded panes are kept in memory to speed up subsequent accesses. Next up: the toolbar.
-
Greg Hurrell
When switching between panes, a dissolve transition is used just like that in Apple's System Preferences application on 10.3. Now that I've written the code for this, I might see if I can find other creative uses for it in other places (specifically, I am thinking of some windows in GetSmart Pro which could also use the effect). Very happy with the appearance of it.
Needless to say, I've also implemented the older 10.2-style switching, where the window animates but does not do a cross-dissolve. Like just about everything else in Synergy Advance and GetSmart Pro I'll make it possible for the user to specify a preference for which transition style they prefer.
Now, back to that toolbar!
-
Greg Hurrell
Ok... the toolbar is now basically done. You can show or hide the toolbar and drag items around on it just like in the Apple System Preferences application. Active panes are highlighted with a tinted rectangle just like they are in System Preferences on 10.3. Again, like the Apple app, you can't drag the "Show all" item around, nor can you get a contextual menu on the toolbar. Customizations made to the toolbar are remembered across runs.
The only thing left to do tomorrow, and this should be very easy to knock off, is making it possible to drag icons from the "Show all" view to the toolbar, and then it's done; an almost pixel-perfect replication of the System Preferences application for use as a preferences window within all of my future apps. The only thing I haven't replicated is the striped shading you see across categories in 10.3; instead I've just used normal separator lines.
The whole system is about 2,000 lines of source code -- including the main class I've developed and the categories I've written to support the class -- but tomorrow I'll go over it and see if I can trim it down a bit. After that, more work on the Synergy Advance core!
-
Greg Hurrell
Created
,
edited
Ok, the preferences window is, as far as I can tell, done (screenshot below). I still have to write the individual panes, but the overall architecture for managing them is complete. The screenshot is a bit boring, I know; you have to imagine it with proper icons, and with more of them... I am looking at using Cocoa Bindings for writing the panes, something I can do because Synergy Advance and GetSmart Pro are both for 10.3 and up only... The idea is to eliminate a heap of glue code between your Models and your Views; unfortunately though, this glue code is replaced with a morass of clicking and binding down in Interface Builder. I guess I won't know if I prefer it until I've tried it, and mastered it. This will be the first time I've used Cocoa Bindings, you see.
[screenshot temporarily deleted due to server reorganization]
-
Ben
Heya Wincent,
Just wandering if there's been much progress on Synergy Advance of late?
Not that we're waiting with baited breath...
Ben
-
Greg Hurrell
Quote: Heya Wincent,
Just wandering if there's been much progress on Synergy Advance of late?
Not that we're waiting with baited breath...
Ben
Erm... in this very thread if you look over the last seven days you'll see that I've posted a daily progress report detailing what I've done each day... Hehe...
Today: hot key code. The hot key code in Synergy is pretty much welded into the program; much like your spine is an inseparable part of your skeleton. Today I've been working on a much improved, elegant, and reusable implementation of the hot key technology that can be re-used in Synergy Advance, GetSmart Pro, and every other app I release in the future. Without going into details, the code is much more flexible and will allow me to do much more with hot keys...
I'm working full time on this now, getting as much as 10 hours of coding done per day. But the bank account is dwindling rapidly, so I am not sure how much longer I can keep this up for, living off savings. I am making the most of it while I can though!
-
Ben
LOL (at me) for some reason last night where it said "Mar" I was reading "Nov" I didn't that that I'd had THAT much Whisky!!!
Anyway still waiting with baited breath
Ben
-
Greg Hurrell
It's been an extremely busy few days for me. WinSwitch is out (first 1.0 and now 1.1), and I've released two updates to Install and one for Synergy...
But now, back to work on Synergy Advance (and GetSmart Pro... all this stuff I am working on now is common code between both apps).
[Later today (Monday) you'll also see a WinSwitch 1.2 release, which is a major update.]
-
Greg Hurrell
Improved copy protection. These are some major components and I will probably be spending quite a few days on them. I'm also writing up an article for wincent.org to help people understand why I'm doing this...
-
Krypton
Quote: Improved copy protection. These are some major components and I will probably be spending quite a few days on them. I'm also writing up an article for wincent.org to help people understand why I'm doing this...
Is that piracy protection, or something else?
-
Greg Hurrell
Quote: Is that piracy protection, or something else?
Yes, I used "copy protection" as a synonym for "piracy protection". What else would it be?
-
Krypton
Maybe for album covers, I don't know. Having not explicitly said 'piracy' I thought that your use of copy meant something else...
-
Greg Hurrell
For the past couple of days have been working on a revamp of the website. I will be migrating all of my sites over to the new look and using a consistent nav bar across all the sites for easier navigation. For example, some people wind up at wincent.org when they're really looking for wincent.com and vice versa. I will be trying to make navigation as straightforward as possible, across all the domains I control, including these forums (forums.wincent.com), the bug-tracking website (bugs.wincent.org) and the product websites (such as synergy.wincent.com). I've now got some nice PHP that automates the dynamic elements in the nav bar.
-
Greg Hurrell
Have set up a secure subdomain using SSL to provide an additional degree of security when interacting with customers, for example, during product activation, or when retrieving lost serial numbers etc.
-
anonymous
It's now May 6th (PST time zone, at least). I thought you were posting regular day-to-day reports, yet your last report was the 15th! What happened?
-
Greg Hurrell
Quote: It's now May 6th (PST time zone, at least). I thought you were posting regular day-to-day reports, yet your last report was the 15th! What happened?
I will shortly be rolling out new versions of Synergy and WinSwitch. More on progress that's been made with Synergy Advance (and GetSmart Pro) later...
-
Greg Hurrell
More work on hot keys.
-
anonymous
Any more news on Synergy Advance progress? Or anything new happening with Synergy?
-
zerock
any news on new synergy or synergy advance, i cant wait
-
Greg Hurrell
Synergy 1.0 is almost ready to go out the door.
-
Greg Hurrell
Quote: Synergy 1.0 is almost ready to go out the door.
And out the door it did go...
Apart from that, today I've been working on a bunch of code for working with the "iTunes Music Library.xml" file which will allow me to make a lot of shortcuts by operating directly on an internal representation of the music library instead of having to do everything via iTunes (using AppleScript and Apple Events).
-
Greg Hurrell
More work on parsing the XML file and leveraging it. To speed up development, I've split the code up into two parts: "the app", and "the Synergy Advance framework". This is in addition to the base framework that I've already put a lot of work into and which is used in a couple of my other apps. The idea is that by having the code in the framework I can reuse it if the project ends up heading in a direction that I hadn't originally anticipated.
I was originally planning an App/PrefPane combination (just like Synergy), but I think that things will be simpler if Synergy Advance is just a straight App.
In any case, did a bit of work on the Synergy Advance framework (called Synergy Core) in the area of error handling, exception handling, and Apple Events.
Did a bit more work on WinSwitch today too. I know I just released a new version, but based on feedback I've received I've already added a couple more features.
And over the past couple of days I've been in discussions with some other developers who manipulate album art in their apps; looks like we could arrive at a standard for storing album art (for people who don't like to embed it in their audio files) and which all these apps could access.
-
anonymous
Quote: And over the past couple of days I've been in discussions with some other developers who manipulate album art in their apps; looks like we could arrive at a standard for storing album art (for people who don't like to embed it in their audio files) and which all these apps could access.
This is great, I'm glad you're open to using a standard album art location. As more and more apps make use of album art it would be really nice not to have hundreds of megabytes duplicated in different places on the hard drive. And it makes it more likely that other apps will take advantage of artwork not stored in iTunes.
-
Greg Hurrell
Worked on extracting useful information from the iTunes library file and storing it in memory in various formats for quick access. Given that the library in question could be huge, all of this is done in a separate thread, so I've spent a bit of time ensure that this info can be accessed in a thread-safe manner even in the middle of a refresh. The other thing I've done is use an additional, periodically released NSAutoreleasePool inside the tight loops so that the memory footprint won't swell too much if the user has thousands upon thousands of tracks.
-
Greg Hurrell
I've been replicating some of the iTunes interface within Synergy Advance. Ok, I tell a lie: I'm actually doing the groundwork for that replication.
Apparently Donald Knuth said that "premature optimization is the root of all evil" (although I don't know where he actually said this), but even so, I've been engaging in some sensible design practices to makes sure it's fast. In fact, it's more just commonsense design rather than optimization. iTunes is fast even with a 10,000-song library, so I want Synergy Advance to be fast too.
So I guess this just means avoid brain-dead attempts at scanning the entire library; if the user is only looking at one album, you should be able to work only within that subset.
-
Krypton
Quote: Quote: Apart from that, today I've been working on a bunch of code for working with the "iTunes Music Library.xml"
Yay!!!!!
-
Greg Hurrell
Well I've finished the underlying stuff and have started the higher-level GUI elements for allowing the user to browse the entire library quickly.
But, on a bit of a tangent, I've just today started work on a new product. It's something I've wanted to do for a while, and it's something that I can start off nice and small, so it hopefully won't take too long. Why I am doing this?
Well, it's because I want to learn how to use Cocoa Bindings, which are new in 10.3. I've looked at the docs several times since 10.3 came out, read the tutorials, and just haven't been able to "get it". The idea is that you can throw out a huge amount of glue code and replace it with work in Interface Builder. But the documentation was incredibly opaque to me and I couldn't see how I would be more productive by throwing out all that code and replacing with a lot of fiddly clicking and facing a bewildering array of options in Interface Builder.
Nevertheless, I know that this Cocoa Bindings stuff is a "good thing", so I figure the best way to learn it is to start off with a clean slate (a new project) and write it using Cocoa Bindings from the very start rather than trying to graft it onto an existing project.
After one day's work on it (most of it spent scratching my head trying to make sense of the documentation) I'm quite happy with what I've been able to achieve using NSUserDefaultsController. Basically, having written very little code, and doing most of the work in Interface Builder, I know have a fully functioning preferences window with quite a few interconnections and live updates going on, default (initial values) are working, and everything is getting nicely flushed to disk. All of this in addition to the usual stuff you can do in Interface Builder in the way of hooking up delegates and connecting windows to menu items etc.
The project (which for now will remain a secret!) will be making use of NSTableViews and NSSearchFields, so it should allow me to come to grips with quite a few aspects of Cocoa Bindings that I can then leverage in Synergy Advance and GetSmart Pro. And not only that, the project I am working on is designed to boost productivity, so the sooner I finish it, the sooner I can start reaping the benefits.
This is also my first chance to roll the new, improved hot key code that I've been working on in the WOBase framework into an app, so that will be a good test for it too.
-
anonymous
sounds interesting. i like these progress reports btw, so keep them up. it's interesting to hear what you're working on.
-
Greg Hurrell
The communication between Synergy Advance and iTunes is performing really well under testing. Even if iTunes stalls and blocks Apple Event requests, the Synergy Advance UI remains responsive. I am very happy with it; not only from a performance perspective, but in terms of robustness and flexibility, it handles CD tracks, shared playlist tracks, radio tuner tracks, and I suspect even iPod tracks (I don't have an iPod to test it on, but the support is in there). I'm spending a lot of time making sure that I can process just about anything that iTunes can throw back, so there should never be times when Synergy Advance doesn't know what to do with the reply from iTunes.
I've been able to design in support for all these sources from the beginning, rather than layering them on one by one at a later time, so it means that the whole thing can be more elegant and work more efficiently. I can basically get more information from iTunes, and update with increased frequency, without causing any "stuttering" in the visualizer like some users with slow machines have reported under Synergy.
-
Greg Hurrell
More work on Synergy Advance/iTunes comms, and more work on my "mystery app" (hehe).
I've got to say, I am still far from comfortable with Cocoa Bindings, but I am gradually getting it to do what I want: so far I have two windows with NSTableViews in them, dynamically updating item counts, working add/remove buttons, and they're automatically updating as new data arrives.
So far just sticking with basic text-only content, but the next items to cross on the learning curve will be: implementing drag-and-drop to re-order within each NSTableView, implementing drag-and-drop between the two windows, supporting the delete key in the NSTableViews, and hooking up the search fields that I've already got in each window.
The cursor keys already work in the NSTableViews, but I want to add type-ahead incremental search. Looks like all of this stuff means I'm going to have to subclass NSTableView.
Once I've got those basics working I'll add support for non-text content.
This things are minor UI details from the end-user perspective, but I think they make all the difference when it comes to the perceived quality of the user experience. UI polish! The app should behave intuitively. The user shouldn't have to consult the menu. They should be able to look at something and think, "I wonder if I can drag that to rearrange it", or, "I wonder if I can navigate everything from the keyboard" etc and it should all "just work".
All of this will most likely take a day or two (or more) while I get to grips with Cocoa Bindings, but hopefully it will pay off in the long run because I'll be able to apply the techniques in other apps.
-
Greg Hurrell
Drag-and-drop to re-order now working (still have to handle dragging between windows). Search fields hooked up. Status text now says stuff like "Showing 14 of 25 items, 1 selected".
I've just learned how to simulate keyboard events in other applications, which I need to be able to insert things into other apps (as though the user had pressed Command-V). Good.
-
Greg Hurrell
I've worked out how to do hardware-independent keycode mapping.
The problem with the keycodes generated by your keyboard is that they are dependent on the hardware you're using and/or the keymap that's active. What this means is there's no way I could provide a set of standard hot keys that would work "out of the box" on all systems for Synergy. Amazingly, the letter "A" (for example) doesn't have the same keycode on all systems.
To get around this problem, Synergy ships with very few pre-set hotkeys (just a few function keys for play/pause, previous and next). The idea is that the user then configures the hot keys for other functions to taste. Because the keys get configured on the machine, the hardware/keymap dependency doesn't matter, because you capture the hotkeys on the same machine that you use the program.
Well, I know that it should be possible to get around this hardware dependency because Apple can and does do it. For example, the default keys used to control Expos
-
Krypton
How close are you (roughly) to a release now Wincent? Not only would I love to have all these features you've been describing, but I'd quite happily send the upgrade fee etc
-
Greg Hurrell
I can only say "when it's done" because I am don't want to make any predictions and then have people disappointed... working particularly hard on things this month because I finished the course I was doing and have more time available now. Won't be starting another course until October.
-
zerock
looking forward to this app , cheers.
-
Greg Hurrell
Arghh. I've been pulling my hair out of the last few days trying to replicate the key-binding interface in Xcode, and correcting a couple of inconsistencies and UI problems in the Apple implementation. You know the drill: spending days trying to reverse engineer, trouble-shoot and account for mysterious, undocumented behaviour etc.
I've spent a lot of time trying to troubleshoot stuff that should be incredibly straight-forward, but isn't... but at least now am making some progress. I'm now into the meat of it, working on implementing the functionality I want rather than trying to work out what Apple is doing behind the scenes.
Another little issue to solve is how to use Cocoa bindings with my custom classes. They are subclasses of stuff for which you can configure the bindings in IB, but in the Bindings inspector nothing shows up. I would like to think that I could somehow set it up so that the Bindings options are just inherited, as they should be! I haven't made any changes in the subclasses which would break Bindings...
-
Greg Hurrell
One by one I go crossing items of my "to do" list with respect to my new hot key capture classes. I'm a perfectionist, so I'm trying to replicate the Apple Xcode behaviour where it's good, and eliminate or improve bad behaviours.
Stuff I've been able to cross off the list today: text appearance in the custom field editor matches that used by the default field editor associated with NSTextFields; drag and drop refused (as recipient); drag and drop refused (as source); ghosted image suppressed if user attempts to initiate drag; contextual menu suppressed; inappropriate menu items invalidated (cut, copy, print etc); don't end editing on tab, enter, return, shift-tab etc.
Next problem to solve is to get the focus ring showing again. For some reason it isn't...
-
Greg Hurrell
Quote: Next problem to solve is to get the focus ring showing again. For some reason it isn't...
I just want to complain a bit about one of the less publicized Cocoa "Design Patterns". The focus ring problem is fixed, but at the cost of hours of headache-inducing problem solving, trying to work out the undocumented, unexplained, mystery behaviour that Apple is engaging in behind the scenes.
One of my favourite things about Object-Oriented programming is inheritance. You want to customize the behaviour of a class, so you subclass it. Inheritance means that you don't have to rewrite the entire class; you only need to surpress the behaviours you don't want, add the behaviour you do want, or modify the existing behaviours according to taste. It's a wonderful time saver and very efficient. In my opinion it could well be the single best thing about OO programming (that, and encapsulation).
Thanks to Apple's trickiness, however, I have now spent several days extending a group of classes that interrelate in complex, undocumented and mysterious ways. In fact, sometimes we're not only talking about an absence of documentation, but of actual behaviour that flies in the face of what the docs promise.
I don't want to waste any more time on this than I already have, so I'll be brief. In short, I've been working on a group of three subclasses: an NSTextField subclass, an NSTextFieldCell subclass, and an NSTextView subclass.
The most obvious thing to do when you make this kind of subclass is to start with an empty subclass. It literally does nothing different than the parent class; all the behaviours are identical (inherited), only the name is different.
The idea is that you add or subtract functionality line by line, testing along the way.
But what happens when even the empty subclasses don't work?
Let's just give one example. Names simplified for the purposes of illustration.  You can "trick" IB into doing what you want by telling it that your NSTextFieldSubclass is really a custom view.
That's the easy part, although you can waste a lot of time on it if you don't know the trick.
Next up you try to supply your custom NSTextViewSubclass as a custom field editor instead of the default one provided by Cocoa. You do this in the setUpFieldEditorAttributes method of your NSTextFieldCellSubclass because you want your group of classes to be a neatly contained cluster and you don't want to break the OO paradigm and start messing with your NSWindow delegate. The Cocoa docs explicitly say you can do this. So you do it.
Even though your NSTextViewSubclass is identical to the NSTextView subclass in all but name, you find that once you start using it things are horribly broken. You can't tab between text fields. There are no focus rings. etc. This is the case even if you painstakingly analyse the attributes of the default field editor and replicate them in your subclass.
At this point you break out the debugger, start single-stepping through the code, and peppering your source with log statements to help you figure out what's going on and why your code doesn't work despite the Apple sample code which claims it should.
You begin to suspect that somewhere in the parent classes, Cocoa is doing something nasty, something secret, and is somehow checking for the existence of the non-subclasses NSTextView object and basing its behaviour on that.
Turns out that the drawWithFrame:inView: method is the first culprit. The super class is doing some kind of test. If it gets an object other than the one it expects, it doesn't draw a focus ring. Now, as I don't have access to the Cocoa source code, I can't say whether it's checking for an object of the NSTextView class, or if it's actually expecting the shared instance of the default field editor.
So this means that instead of leveraging the behaviour of the parent class, you have to rewrite it, and you have to rewrite it without access to the source code. It is a horrible, wasteful effort, and if Apple decides to change the behaviour in the future you will have to change your code to match rather than automatically inheriting the changes.
I won't go into further detail here, but this is a "Design Pattern" I've seen time and time again in Cocoa. Cocoa works great if you don't ever want to extend it. The trouble is, if you want your apps to be like Apple's apps, you have no choice but to extend, because they are constantly introducing non-standard widgets that use private APIs.
It's just a shame that "extend" here actually means "rewrite", and the end result somehow always ends up feeling like a fragile kludge. Sometimes I just love Cocoa; other times I just hate it. Now is one of the latter times. I've spent about four solid days so far battling against this beast. I've so far spent less than 10% of my time doing what I would call productive work (ie. implementing custom functionality that provides me with an end-user UI widget which meets the special requirements I have in mind) and the other more than 90% of the time fighting tooth and nail against Cocoa, reverse engineering things that I shouldn't have to reverse engineer, and constructing fragile, verbose replications of functionality I should be able to easily inherit.
It's times like this that I wish a little bit more of Mac OS X was open source. At least then I could look inside and see what hideous shenanigans they're getting up to behind the scenes.
Urggh... Anyway, time to get back to the hell hole...
-
Greg Hurrell
Ok, made some real progress last night/today, and so I'm a little more calm... hehe... I managed to solve most of the problems I was having by zeroing right in on the methods for which the Apple documentation is incomplete or downright misleading (the culprits:
-
Greg Hurrell
Quote: As a "reward", I am going to distract myself and spend a bit of time learning about Subversion.
And this is the result.
-
Krypton
Could we have a screenshot of your latest work (like you used to do with Synergy)? Provided that there's something to take a picture of of course
-
Greg Hurrell
Created
,
edited
Quote: Could we have a screenshot of your latest work (like you used to do with Synergy)? Provided that there's something to take a picture of of course
I am sure this isn't what you were hoping for, but here it goes anyway:
[screenshot temporarily deleted due to server reorganization]
This is a sneaky glimpse into the glamorous process of software development...
I've now polished this hot key code so much that I've got it working better than even Apple's own. I've been using the Key Binding preferences in Xcode as my bench mark, and now I can correctly detect keys that even Xcode fails to see. I've got a Spanish keyboard too, so those strange looking characters you see correspond to keys on that (like
-
anonymous
It sounds like you have enough on your plate already, but it's occurred to me that the knowledge you've gained developing Synergy, Synergy Advance, etc. could make for some really valuable articles. It sounds like you have a lot of knowledge about areas where Cocoa falls (far) short of what it promises. Not only do you know how it fails, but you've figured out workarounds. If you ever have spare time, or want a break after SA 1.0 is out the door, I think a couple articles detailing these things that Apple glosses over, or is misleading about in its own documentation, would be really valuable for the Mac developer community.
-
anonymous
Maybe you could even freelance for MacTech or O'Reilly or something...
-
zerock
so whats next?
-
Greg Hurrell
Quote: so whats next?
I've just gotten back to Spain after being in Australia for a couple of weeks. While over there, I continued working on my hot key classes, and also did some more work on security stuff; eg. binary signing, I also came up with a modified base-32 notation system which will be used for registration and should make it much easier for customers to enter their serial numbers.
I also wrote lots of unit tests, and am pleased to report that they really helped in both catching bugs and also confirming when the implementation was where it should be.
There are a lot of people who base their entire coding practice around unit testing. They write the tests before they begin the rest of the code. When the tests pass, you know you're done.
I don't work that way because it doesn't suit the way I think. I start with a general idea of what the code should do, and I have a few specific sub-goals. I can generally write the unit tests for those sub-goals straight away (basically, as soon as I've decided on the class and method names that I'll use in solving the problem). But along the way, I think of other sub-goals that need to be met, or I become aware of subsidiary problems that need to be solved as stepping stones towards the big problem, and so I'll write more unit tests as I go along.
Basically, I'm not using the unit tests as an integral part of the development process (in the sense of using them to drive code production); rather I am largely using them for quality control. It's great to know that if you introduce a bug somewhere down the track you're unit tests will pick it up, and that means you write better software with fewer bugs, and the users wind up having a better experience.
-
Greg Hurrell
Today I finally put the finishing touches on the modified base-32 system and I now have it handling all the edge cases. I've thrown a lot of unit tests at it, including getting it to round trip massive hunks of pseudo-random data from NSData to a string representations and back again, and it passes with flying colors. It's now officially "done", and thanks to all the unit tests I am quite confident that it's likely to be bug free.
-
Greg Hurrell
Today's accomplishments so far: an NSObject category, and made sure that the "+" and "-" buttons in my custom field editor (used for capturing hot keys) aren't displayed when the window is not the key window.
-
Greg Hurrell
Quote: 6,120 framework lines, 747 Synergy Advance-specific lines.
It's been a while since I posted a source code line count. Quite a bit of progress has been made since then. Just ran another count and now I've produced 12,506 framework lines and another 3,390 lines in the Synergy Advance-specific part of the codebase.
My next, super-secret, mystery app (ha), which uses the framework is 659 lines so far. Needless to say, most of the work occurs in the framework at the moment. Thanks to Cocoa Bindings, the amount of code in the actual app itself is vastly reduced.
Now that Xcode 1.5 is out, I noticed that they've ironed out a couple of glitches in their keybindings UI. In previous versions you could assign multiple key combinations per item. Now they limit you to one. I've designed my own hot key stuff to match the Xcode UI, and originally intended to allow you to set multiple key combinations, just like Xcode. Now that the Xcode behaviour has changed, I am thinking about whether or not I should match it. I'm thinking that perhaps it would be best to keep the added functionality in there rather than strip it out.
One question remaining to be solved, however, is what to do when the user defines so many combinations that the field editor needs to scroll to provide access/show them all. Yesterday I implemented the code that prevents the "+" and "-" buttons from getting overwritten by text (or more accurately "underwritten"; in the older versions of Xcode you could enter so many combinations that they spread across and eventually started to slide "under" the buttons). But what's the best way to implement scrolling within the field editor? You can't scroll with the cursor keys (after all, the field editor needs to be able to capture the cursor keys if the user wants to set them as hot keys). I am thinking it'll have to be a mouse-only affair. And I am thinking also that I am going to suppress display of the cursor and do it all with highlight rectangles (basically matching the Xcode behaviour). That will be another nice mystery to solve... how, or where, does Cocoa (and NSTextView) display that cursor? One thing I am sure of is that it's not being drawn in the view's -drawRect: method, because the cursor flashes on and off and the -drawRect: method doesn't get called. I suspect it's getting drawing into a tiny subview that gets inserted on top of the NSTextView...
-
Greg Hurrell
Made lots of progress on finishing off and polishing my hot key capture user interface.
Deleting single or multiple combinations now works, adding, replacing single or multiple combinations, clicking to select, dragging to select forwards or backwards, the add and remove buttons work etc.
All in all it's come along very nicely. Hopefully will be able to finish it today. Things still to do include handling the case where the user switches windows or text fields and a blank "place holder" is in place (need to clean up the place holder)...
-
Greg Hurrell
Spent a few hours today trying to get a certain behaviour and in the end it looks like I am going to have to give up. There are simply too many problems with the approach.
I wanted to make it so that a user could end a hot key capture session by clicking anywhere outside of the active text field. The standard Cocoa behaviour for all such widgets is that they only lose their active status if you click on something which can take over the active status (or become "first responder", to use the Cocoa parlance).
With the hot key capture text field, whenever you enter a new hot key combination, it's highlighed (try it in Xcode and you'll see what I mean). If you type another key it immediately replaces the previous combination.
I wanted to allow the user to click elsewhere in the window to end editing and thus prevent accidental erasure. Once again, you can see this in Xcode: the only way to end editing is to click on another object in the UI which can take over first responder. Merely clicking elsewhere (on something that can't assume first responder) in the window won't do it.
This is a trickier task than it sounds. By definition, the active text field gets "mouse down" events only if they occur inside it. You need to work out a way to be notified of such events outside the text field.
My first attempt was to set up a tracking rectangle which enabled me to detect whenever the mouse left the field. On leaving, I would use NSApplication's nextEventMatchingMask:untilDate:inMode:dequeue: method to watch for mouse down events.
This worked in the sense that I could pick up the events, but it broke some things too. For example, the cursor in the active editor stopped flashing, and I didn't get any key down events (which defeats the purpose of the text field). Also, it would only work if the mouse left the confines of the text field. If it started outside of them (as could be the case if the user used the tab key to get into the text field) then no tracking could be performed.
I was able to fix a couple of these problems by using the NSDefaultRunLoopMode instead of the NSEventTrackingRunLoopMode (this meant that timers could fire and my cursor would continue flashing), and by listening for and appropriately forwarding the other events that I was interested in (such as key down events) so that I could continue to handle them even while tracking.
To cure the "mouse starting outside of the text field" problem, I could actually set up a tiny fake tracking rectangle around the mouse pointer (wherever it might be) and start the tracking as soon as the user move the mouse. It seems that there was no reason why the tracking rectangle had to be inside the text field view itself, so I could put it wherever the mouse was.
Even so, there was other breakage. Cursor rectangles didn't work any more because I didn't know where to forward NSCursorUpdate events, and neither did I want to rewrite the functionality already present in Cocoa's cursor rectangles system. Nor do I want to lose the functionality. For one thing I want cursor rectangles to work in the other parts of the window, but I also want them to work inside my text field, where I've got it set up to show an I-Beam cursor over the textual part and an arrow cursor over the "+" and "-" buttons.
Also, the system didn't handle things all that well when my app lost frontmost status (it would still be tracking). On bringing it to the front again the windows wouldn't actually come to the front (because they were still busy tracking). So all this meant that I had to add code for watching for application switched events, and while I was at it, code for handling when the mouse cursor left the active window and/or the user made another window in the app the "key" window.
By the time I got this far I was wondering if it was all worth it to implement this behaviour that was different from the Cocoa norm. I would do it if it could be done elegantly and without breaking other expected behaviour, but it just didn't seem to be a worthwhile trade-off.
Another alternative which gets around all of the problems above is to create a transparent window that perfectly matches the main window in size and watches for clicks. It lets clicks go through to the text field, of course. Any other click it catches and uses it as a signal to stop editing.
Once again, the "not elegant" alarm bells start ringing when I have to do stuff like watching for when the parent window is moved or resized. At present I haven't attempted this solution, although I believe it should be possible. As I said, I've begun to wonder if all this work and machinery is worth it to meet the goal I've got in mind, especially since I am not entirely sure that the goal is a good idea in the first place.
Off course, all this while I am wondering if there's some easy-to-use method somewhere in Cocoa that I've overlooked. You know, an NSView method called, "-setResignFirstResponderOnClickOutsideOfView:" or something like that... If anybody knows of such a method, I almost don't want you to tell me about it...
In any case, I don't feel too bad about wasting the morning, because I've learnt some things about event tracking and run loop emulation that I didn't know before.
-
Greg Hurrell
Latest counts of lines of source code:
WOBase 14,007 + 273 SynergyAdvance 3390 (still) ??? 717
Progressing very quickly indeed now, apart from a few little setbacks that wasted some odd hours here and there (annoying stuff like a glitch with my mailserver...)
-
Greg Hurrell
WOBase now up to 15,266 lines...
-
Greg Hurrell
Very pleased to report that I've finished coding a set of four classes that I have been working on for two days solidly now. Together they weigh in at around 1,500 lines of code.
It's a set of classes that provide a nice GUI widget for entering license codes. Yes, exciting stuff. Easy enough to write basic widgets, but to override the Cocoa behaviour to provide a really elegant and polished user experience? It's a bit hard to describe in words, so you'll have to see it when it comes out. But when you do see it, you'll understand what I mean.
It required me to use a custom field editor again. Much easier the second time round that you try it! Admittedly this one was not as complicated as the one I had to write for my hot key capture classes.
So in the 24 hours since I last posted the WOBase code count has actually gone down to 15,230... It just goes to show that hours of work doesn't always translate to lines of code. In this case, however, along with the line count going down, the number of things on my "to do" list also went down!...
-
Greg Hurrell
I've been very busy the last few days, putting in at least 12 hours a day on this stuff. There's not a lot to comment on right now. I've got a few things that are coming together, and they'll all be ready about the same time. We're talking about a new product release, updates to Synergy and WinHex, and a total revamp of the website. Hoping that all this will be out in public by the end of September. It's going to require a lot of work between now and then, but I'll certainly be trying!
So I'm probably not going to post here for the next few weeks... But then there'll be some announcements!
-
zerock
nice!! , looking forward to updates, and for Synergy Advance sometime this fall
-
webmacster87
Hmmm...no updates in almost one month? Is anything new?
Have you ever considered making a blog for this?
-
Greg Hurrell
Quote: Hmmm...no updates in almost one month? Is anything new?
Have you ever considered making a blog for this?
As I just mentioned in another thread, I'm thinking of releasing some of the source code modules for Synergy Advance in the form of tutorials posted to wincent.org. But that is still some way off, after the release of 1.0.
In any case, lately I've been working on some nice notification bezels. If you want to get a sneak preview of these, you'll see them in the next version of WinSwitch, which I should be releasing with the next week or two.
-
zerock
Quote: Quote: Hmmm...no updates in almost one month? Is anything new?
Have you ever considered making a blog for this?
As I just mentioned in another thread, I'm thinking of releasing some of the source code modules for Synergy Advance in the form of tutorials posted to wincent.org. But that is still some way off, after the release of 1.0.
In any case, lately I've been working on some nice notification bezels. If you want to get a sneak preview of these, you'll see them in the next version of WinSwitch, which I should be releasing with the next week or two.
have you considered Growl in a way of notifications or is it still too basic? anyways if you dont know about them yet, you can find the growl project at www.growl.info . anyways maybe you will want to include your ownz bezel in synergy advance( i think its the best idea), but you could leave it free(in the future), to use maybe a plugin like a growl module perhaps..
-
Greg Hurrell
It's been a long time between progress reports because I've only had limited access to the Internet. (I had to wait 40 days for an ADSL line to be installed, courtesy of Spanish ISP, ya.com; their customer service is absolutely terrible, and no amount of phone calls or formal letters of complaint could make them lift a finger to get the line installed within what they claim is their typical time span of 2 to 4 weeks. Now I've got the line at least; the connection is exceptionally good, just the opposite of their exceptionally bad customer service!)
Nevertheless, during that time I've been busy at work on a lot of things. It's been very frustrating because without net access I can't access the latest documentation, mailing lists, or do Google searches... but now things are moving very quickly again.
There's been an interesting domino effect, starting with Synergy Advance. Let me explain...
A while ago I decided to have a crack at mastering Cocoa Bindings (new in Panther). I had an idea for a simple project which I could use as a test bed. So I learnt a lot about Cocoa Bindings doing that project, and it's nearly ready for release.
There came a point where I wanted to do something tricky which would come in handy for both that project and also for Synergy Advance, so I figured I would roll the change into WinSwitch. It was like starting with a clean slate, because WinSwitch didn't use any bindings. Thanks to those changes I've got a huge update (version 3.0) almost ready to release.
One of the new features in WinSwitch 3.0 is hot key support. I'd already done a lot of work on hot keys for Synergy Advance, but that was based on intercepting the hot key events at the level of NSApplication.
This wouldn't work in WinSwitch, because WinSwitch is not an application. So I figured out how to do it more elegantly by using a Carbon event handler. I figured I may as well split all this hot key stuff into a separate framework, because I didn't want to include WOBase (the framework into which I was previously putting common code for Synergy Advance, GetSmart Pro etc...) in WinSwitch.
So WOHotKey was born, and did a lot of work polishing it and making it nice and reusable.
A lot of the stuff I was working on required access to docs and online information. Seeing as I couldn't spent too much time in the Internet Cafe every day, I went off on a tangent and made a unit testing framework, WOTest. I'll be releasing this shortly. I wrote it because, as is often the case, none of the offerings currently available behave exactly as I want, and I would rather write my own custom solution than try to beat someone else's solution into shape to fit my preferences. Prior to this I had done all my unit testing with a fairly elaborate set of macros. They worked very well, but there was no flexibility and no integration with Xcode. The new unit testing framework addresses both of those shortcomings, and I'll even be able to ship the tests with my products, for those who are interested in running them, without increasing the memory demands for people who don't want to run the tests. This could come in handy if a user with a strange configuration reports a bug that I can't reproduce here; they can run the unit tests and see exactly what is failing on their machine.
The next domino fell when I realised that getting WOHotKey to work with Cocoa Bindings was a bit beyond me. Time for more learning... So I've started a new project, once again with the idea of getting an ever better grasp of the bindings technology. I've also used it as an excuse to use a plug-in based architecture for the first time. This project is very close to release as well... All this stuff relates directly to Synergy Advance.
The latest step I've done is split out my bezel code into a new framework, WOBezel, which will also be used by the new WinSwitch, and the other new app I'm working on, and Synergy Advance etc... Today I've been wrapping all this up in an Interface Builder palette (another first for me) so that I can set up these bezels using the GUI rather than programmatically.
So basically I have all these dominos falling; one thing leads to another, and the effects flow back up the chain too. I've got two new products extremely close to release, three new frameworks (WOHotKey, WOTest and WOBezel) of which one will be released to the public (WOTest), a huge WinSwitch update just around the corner, and all of this I will be able to use in Synergy Advance.
Although the coding side of things is almost done, there's still all the administrative side (setting up and updating the websites, writing up the docs, FAQs etc). There's also the piracy problem. These two new apps will be 5
-
Greg Hurrell
Lots of work on the Synergy Advance preferences UI. Threw out old comms engine and started a new, highly-efficient one. New Floater classes (much more MVC compliant); the Floater itself is radically different to the one you see in Synergy. Added WOHost class to WOBase. Finished refactoring to distribute code between WOBase, WOBezel and WOHotKey. Swore repeatedly at my machine which is so slow that when I have multiple projects open in Xcode (for example the app I'm working on, its frameworks and its preferencePane bundles), it beachballs so often and becomes so slow that I feel like I am typing in an SSH session over a 300 baud modem to a server in Alaska.
-
Greg Hurrell
Total rewrite of syneryd background daemon; have shaved off every byte of memory use and every CPU cycle possible, so it now runs in about 100k of physical RAM and uses effectively zero (and I mean zero) CPU: Code:sol:~/trabajo/build wincent$ ./synergyd & [1] 22056 sol:~/trabajo/build wincent$ leaks 22056 Process 22056: 1050 nodes malloced for 83 KB Process 22056: 0 leaks for 0 total leaked bytes. Refactoring and cleanup of WOPreferenceWindow class; now named WOPreferencesWindowController to more accurately reflect its purpose. Set up build chain with app, frameworks, custom preference panes etc to produce first running build of Synergy Advance! (previously I've only run segments of code in test apps)
-
Krypton
That's good to hear! (the running build that is)
-
Greg Hurrell
I've been very busy with the site redesign and getting Synergy 1.5b out the door, but now finally have some time to make some more progress on Synergy Advance.
I recently decided on a release date for Synergy Advance. It will come out very close to the time that Apple releases Mac OS X Tiger. Although that date still isn't publicly known, I'll move heaven and earth if necessary to get Synergy Advance out at the same time. So that means first quarter, 2005, most likely.
The reason is that I want to take advantage of some new features in Tiger. I haven't yet made a commitment to whether the app will support Panther or not (the decision was made long ago not to support Jaguar). Clearly I would like to support Panther, if I can. It's certainly the plan, but it all depends on whether any unforeseen difficulties crop up. The idea is that the app would run on either OS, but some of the functionality would only become active on the newer release. I haven't even installed Tiger yet, because I haven't wanted to install anything pre-release on my production machine. But I will be installing it soon and Tiger-centric development will start in earnest.
You know how I was gloating about the first running build of Synergy Advance in my last post. I soon got into some really ugly refactoring work of a very important class which is over a 1,000 lines of code which meant that I couldn't do any working builds until the refactoring was done. Then like I said, the site redesign and Synergy 1.5b came along. It was only last night that I finally finished the refactoring and got the builds working again.
Now I have two little blocking issues that I have to address which are holding me up. Once I have these issues resolved I'll be able to get WinSwitch 3.0 out, as well as another brand new app I have under development soon after that. All of this code is used by Synergy Advance too.
The two issues are:
(1) A set of four small UI bugs in my hot key framework that I want to iron out. They are not show stoppers, but I don't want to deploy it until it's perfect. Hoping to get these squished today.
(2) Getting the hot key frameworks to play nicely with Cocoa Bindings, specifically with respect to writing/reading user preferences to/from disk. Yes, that's right, my love affair with Cocoa Bindings (yes, that is irony) continues. Once again, hoping to get this "burninated" today.
-
Greg Hurrell
Well I did indeed get all those things done that I wanted to get done. A miracle. I'm currently banging my head against the wall trying to get an Interface Builder palette together for my custom classes. The lack of documentation is a bit frustrating, and the mailing list is full of posts saying "it's easy, just do this", but I can't get it to work.
At least there is a fair bit of sample code in /Developer/Examples/, but haven't had any luck yet, even with a simple NSTextField subclass. Hopefully will get it fixed soon, because this has me pulling my hair out.
Once I've got this done the next hurdle is to make a custom palette for my NSWindow subclass. From what I've seen on the mailing list, this is distinctly tricky and requires some kind of unspecified hack, and not an example in sight. Let's hope I lose only one day to this rubbish so that I can get back to the real work.
-
Greg Hurrell
Ok, so I got the Interface Palette working nicely for my custom hot key framework, and it all plays nice with Cocoa Bindings. (A miracle.) I still have to make a palette for my bezel framework, and it could be a little bit tricky from what I've read about putting NSWindow subclasses on IB palettes.
I got a bit distracted these past two days and have come up with a crash catcher/crash reporter framework, much like you see in Omni products (or Mozilla and Camino pre-releases, from memory).
It all started when I was reading about how to print stack traces from within a running app. Never one to do anything by halves, I decided to wrap this up into a framework called WODebug that I can ship with all my applications. The framework provides stack trace functionality and offers an optional Crash Catcher that will step in and catch uncaught exceptions, signals and crashes, and launch an embedded Crash Reporter app to send the details of the crash to me via email.
This is a Panther-and-up framework, only, so you won't see it in Synergy; but you will soon see it in WinSwitch (although the truth is WinSwitch is so stable you'll probably never actually *see* the crash reporter).
I am very pleased with the framework at this point, although I still have a bit more work to do (like rolling in some logging macros and other basic stuff that I've currently got elsewhere).
It can generate stack traces on demand, and I've got two alternative methods for doing this in place, in case Apple ever changes their APIs. When it catches exceptions, signals and crashes, it really catches them, which means you don't see the Apple crash window popping up alongside the Wincent Crash Reporter. And I'm happy with the UI and I think you will be too. It's very clear about information gets included in the report and it gives you opportunties to review before sending, or to easily turn off the Crash Reporter dialogs if you don't want to be bothered by them, or to relaunch the app immediately.
It doesn't depend on external executables or having the Xcode Tools installed. Support can be rolled into existing apps with a single line of code. The memory footprint of the framework itself is absolutely tiny, so it won't have any impact at all on performance. Most of the material in the framework sits on the disk and never even touches memory, unless there's a crash, by which time it's too late to be worrying about memory anyway. It looks like it's going to add about 220KB to the download size of any product that uses it, but I think the bug-squishing benefits make it a very worthwhile trade-off.
-
Greg Hurrell
Latest source code counts (lines of code):
WODebug: 1,183 WOBase: 13,279 WOHotKey: 4,352 WOBezel: 1,783 WOTest: 3,740 Synergy Advance: 34,183
Total: 57,337
-
Greg Hurrell
I've decided to make the jump to C99 and see what happens, even though GCC doesn't fully support it yet. I just got sick of writing sequences like this: Code:unsigned i; for (i = 0; i < max; i++) {
// do something
} Which would really be better written as: Code:for (unsigned i = 0; i < max; i++) {
// do something
} In these examples the variable "i" serves no purpose whatsoever apart from determining when the loop should stop running. It has always annoyed me that I had to declare it on a separate line.
The GCC Objective-C compiler already supports some of the new features in C99, even when running in C89 mode; things like single line comments starting with "//" and freedom from having to put all variable declarations at the top of function.
What I didn't realise was that GCC's incomplete support for the full feature set -- the thing which was holding me back from trying out C99 sooner -- is actually just about the best support you can get in any compiler (see this Wikipedia entry and this newsgroup summary for more). Given that I always write in pure C or Objective-C (never C++ or Objective-C++), the various incompatibilities between C++ and C99 don't concern me.
I'm pleased to report that on updating my build settings (under "C Language Dialect" in Xcode) that everything pretty much compiles exactly as before with only a few, easily-fixed warnings (that were related to system headers; all I had to do was add a few #import statements to silence the warnings). Will continue to test this over the next few days of coding, but right now it's looking very good.
-
Eerk
Quote: Like just about everything else in Synergy Advance and GetSmart Pro I'll make it possible for the user to specify a preference for which transition style they prefer.
Yes! Optional features and preferences, lots of preferences! You just don't ever know what the end user thinks is his/her prefered way of looking at things and working with parts of the application.
Greetz, Eerk.
-
Greg Hurrell
Instead of keeping separate progress logs for each topic I think I'll just keep one single progress log for all of them. I am putting a lot of work into frameworks that get used by more than one app so it makes some sense to combine the logs. See the new combined log here:
https://wincent.com/a/support/forums/showflat.php?Number=481
Reply
This topic is now closed.


Video controls poster
Video controls width height
Video controls CSS width height
Video controls width height and CSS
Video controls muted


Running a Search¶
To search the database we’ve built, you just run our simple search engine:
$ g++ `xapian-config --cxxflags` code/c++/search1.cc code/c++/support.cc -o search1 `xapian-config --libs`
$ ./search1 db watch
1: #004 Watch with Chinese duplex escapement
2: #018 Solar/Sidereal verge watch with epicyclic maintaining power
3: #013 Watch timer by P
4: #033 A device by Favag of Neuchatel which enables a stop watch to
5: #015 Ingersoll "Dan Dare" automaton pocket watch with pin-pallet
6: #036 Universal 'Tri-Compax' chronographic wrist watch
7: #046 Model by Dent of mechanism for setting hands and winding up
'watch'[0:10] = 4 18 13 33 15 36 46
These results show that 7 documents match our search for the term ‘watch’, providing the document IDs (e.g. #004) and title for each. If you want to search for multiple words, just chain them together on the command line:
$ g++ `xapian-config --cxxflags` code/c++/search1.cc code/c++/support.cc -o search1 `xapian-config --libs`
$ ./search1 db Dent watch
1: #046 Model by Dent of mechanism for setting hands and winding up
2: #004 Watch with Chinese duplex escapement
3: #018 Solar/Sidereal verge watch with epicyclic maintaining power
4: #013 Watch timer by P
5: #094 Model of a Lever Escapement , 1850-1883
6: #093 Model of Graham's Cylinder Escapement, 1850-1883
7: #033 A device by Favag of Neuchatel which enables a stop watch to
8: #015 Ingersoll "Dan Dare" automaton pocket watch with pin-pallet
9: #086 Model representing Earnshaw's detent chronometer escapement, 1950-1883
10: #036 Universal 'Tri-Compax' chronographic wrist watch
'Dent watch'[0:10] = 46 4 18 13 94 93 33 15 86 36
You’ll notice that all of the results from the first time come back the second time also, with additional ones (the match ‘Dent’ but not ‘watch’), because by default QueryParser will use the OR operator to combine the different search terms. Also, because #046 contains both ‘Dent’ and ‘watch’, it now ranks highest of all the matches.


FlaneurImagePickerController
final public class FlaneurImagePickerController: UIViewController
An Image Picker that allows users to pick images from different sources (ex: user’s library, user’s camera, instagram …)
-
The navigation bar of the view controller.
Declaration
Swift
public let navigationBar: UINavigationBar =
-
The object that acts as the delegate of the picker view.
Declaration
Swift
open weak var delegate: FlaneurImagePickerControllerDelegate?
-
Contains all the Image Picker’s configurations, you can override those configs by setting their public properties from inside that object
Declaration
Swift
open var config: FlaneurImagePickerConfig = FlaneurImagePickerConfig()
-
Init
Declaration
Swift
public init(userInfo: Any?, sourcesDelegate: [FlaneurImageSource], selectedImages: [FlaneurImageDescriptor])
Parameters
userInfo
Arbitrary data
sourcesDelegate
Array of image sources, aka: FlaneurImageSource
selectedImages
An array of already selected images
-
A required init
Declaration
Swift
required public init?(coder aDecoder: NSCoder)
-
viewDidLoad Lifecyle callback
Declaration
Swift
override public func viewDidLoad()
-
Notifies the view controller that its view is about to be added to a view hierarchy.
Declaration
Swift
override public func viewWillAppear(_ animated: Bool)
Parameters
animated
If
true
, the view is being added to the window using an animation. -
Notifies the view controller that its view was added to a view hierarchy.
Declaration
Swift
override public func viewDidAppear(_ animated: Bool)
Parameters
animated
If
true
, the view was added to the window using an animation. -
viewDidLayoutSubviews Lifecyle callback
Declaration
Swift
override public func viewDidLayoutSubviews()
-
A DataSource method used to feed the collection with data for a particular list adapter
Declaration
Swift
public func objects(for listAdapter: ListAdapter) -> [ListDiffable]
Parameters
listAdapter
The adapter asking for the data
Return Value
An array of ListDiffable data
-
A DataSource method used to associate a section controller to object of an adapter
Declaration
Swift
public func listAdapter(_ listAdapter: ListAdapter, sectionControllerFor object: Any) -> ListSectionController
Parameters
listAdapter
The adapter asking for the section controller
object
The current object to be associated with a section controller
Return Value
The section controller for the object
-
A DataSource method used to show an empty view in the collection when data for an adapter are empty.
Declaration
Swift
public func emptyView(for listAdapter: ListAdapter) -> UIView?
Parameters
listAdapter
The adapter asking for the empty view.
Return Value
A custom empty view of type UIView.


## Rules
- No change of existing code if not covered by tests
- __Unless__ we make an automated refactoring to add unit tests.
A Coverage Tool can indicate how much code has been covered by testing
- __Readable__ tests (full coverage)
- Basic refactoring
- Replace Global / Singleton / Static
- Check design ([SOLID principles](https://en.wikipedia.org/wiki/SOLID), [Law of Demeter](https://en.wikipedia.org/wiki/Law_of_Demeter))


Officia deserunt mollit anim id est laborum
Cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum veniam, quis nostr
These cases are perfectly simple and easy to distinguish.
But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account.
These cases are perfectly simple and easy to distinguish.
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium,
totam rem aperiam architecto beatae.


Oliver Teams Up With His Daughter in New Arrow Episode 8.05 Stills
by Tudor LeonteA new batch of promotional photos from the upcoming Episode 5 of the eighth and final season of Arrow has made its way online. In the next episode, Oliver and the Team will travel back to Russia. Additionally, it seems like Roy Harper will make his return after the events of Arrow Season 7 finale. The synopsis of the next episode of Arrow reads as follows:
Upon learning the key to oppose The Monitor (guest star LaMonica Garrett), Oliver (Stephen Amell) and team return to Russia on a mission to gather the necessary materials. Diggle (David Ramsey) reunites with a figure from his past.
Laura Belsey directed the episode written by Benjamin Raab and Deric A. Hughes. You can check out the new Arrow Episode 8.05 stills in the player below.
RELATED – Paul Blackthorne Will Return For Arrow Season 8
Arrow stars Stephen Amell as Oliver Queen, as well as David Ramsey as John Diggle, and Katie Cassidy as Laurel/Black Siren. Rick Gonzalez plays Rene Ramirez/Wild Dog, with Juliana Harkavy as Dinah Drake/Black Canary. Charlie Barnett (Russian Doll) joined the cast as Diggle, Jr. — known as J.J. — the Flashpoint-born son of John Diggle (David Ramsey) and Lyla Michaels (Audrey Marie Anderson). We’ll meet J.J. in the future as the leader of the Deathstroke Gang. There he faces off against Mia and his adopted brother, Connor.
Based on the DC characters, the series is executive produced by Greg Berlanti, Marc Guggenheim, as well as Wendy Mericle and Sarah Schechter. Additionally, Bonanza Productions Inc. produced the show in association with Berlanti Productions and Warner Bros. Television.
The next episode of Arrow Season 8 will air on The CW on November 19.


Chocolate Pizza
POSTED ON 15 DEC 2013 / DESSERTS
For the fig-swirl: Melt butter over medium heat in a saucepan. Add brown sugar and stir to dissolve. Halve all of the figs and toss is the saucepan with water and lemon juice. Cook over medium heat, stirring frequently, until you have a chunky-jummy-mixture. Add salt with one or two stirs, set aside and let cool completely.
Ice cream: In a small pot over medium heat, combine milk, and granulated sugar until sugar is completely dissolved and the milk is just barely lukewarm. Whisk in the egg yolks. Set mixture in the fridge and wait until the fig mixture is cooled.
Using an icecream machine, pour liquides into the frozen basin and process according to manufacturer instructions, i.e., let spin and thicken for twinty minutes before adding mascarpone, fig jam mixture, and the nuts. Continue to process for +/- 10 minutes. Pour semi-frozen mixture into a pyrex dish or glass tupperware. Freeze for at least two hours before serving.
Vanessa Stevenson
Food enthusiast, photography fan. Add a pinch of raw foodism and
that's pretty much who I am.


Marissa is definitely as sweet and gentle as she first comes across - but I have the privilege of also knowing her to be a fierce friend, loyal in every situation, and as stubborn as they come. It's pretty rare to find someone that loves everyone they meet and never has a bad word to say about anyone, but one of these rare souls is my sister and one of my best friends. Her art is amazing, and Asian soups divine - if you're ever going anywhere in Asia, bring Marissa. Also don't borrow her erasers (even if you return it she will notice it's out of place hahaha).
Best memories include:
My favourite Christmas present. Originally disappointed she wasn't a brother, later realizing that I'd be completely lost in the water without my fashion/beauty consultant, adviser on why I'm being dumb, and personal comedian. I can't imagine my life without the countless laughs and deep insight Chloe has gifted me with throughout the years. Seriously the gift that keeps on giving. Spicy and sweet, this one's passion for justice, family, and sleep is scary and beautiful all at once. ;)
Best memories include:
One of my best friends. When we first met, neither of us could believe how much our lives and interests lined up - a match made in heaven <3 Aside from having an angelic voice and looks to boot, she has a serious heart for worship and children's ministry and is not afraid to challenge her friends in their walk with Christ. Always game to play duets, eat ice cream, and dive into deep reflective conversations - sorry guys, this woman is no longer available (recently married to another good friend of mine - Josh Ramer!)
Best memories include:
Lindsay has been one of my best friends since moving to Edmonton. We met at a young adults event at church and I instantly knew I found a kindred spirit connected through our mutual passion for adventures, following Jesus, and being super quirky ;) . One of the things I love most about her is her genuineness - she doesn't feel the need to hide her beliefs or thoughts on life, and her passion for leading a life like Jesus's is super inspirational and makes me want to be better! The perfect combination of hilarious and gorgeous.
Best memories include:
I wouldn't be who I am without these men. Let's meet them.
Dawson is the middle Kaefer brother and my best man! He's currently halfway through his engineering degree and if I would ever choose a man to lead a group of people to solitude in a post-apocalyptic world, it'd be him. We lived together at my grandmas house for a year while going to university, and he consistently played the best playlists known to man (yes even that country playlist). He loves hiking and adventuring outdoors, and Elise and I are excited to go on a backcountry hiking trip with him (and his 4runner) one day! Dawson, you are so awesome. Never change.
Best memories include:
Ryan is the youngest Kaefer brother.  Ladies he's single! Ryan has always loved me, and his fierce faith and challenging questions have helped me grow as a person. He always tells it to me like it is, and I've used him as a general decision advisor for many years now without pay. He's away at bible school until April, but he's coming home just for this wedding! Thanks Ryan!
Best memories include:
Josh and I have known each other since we were infants, and ever since then we've made people cry (with joy) with our silly sense of humour. We've experienced vacation bible school together as kids, made Craig Robertson's life hard as youth, and still made Craig Robertson's life hard leading together as youth leaders. Josh's kindness and faithfulness have challenged and inspired me through the years, and I'm honored to have him stand with me on my wedding day. Also I thank him and Luke so much for starting the Big ol Ballas haha
Best memories include:
Luke is an extremely kind-hearted and generous friend that isn't afraid at all to completely annihilate you with chirps when you do something dumb; and I love it! :D I've been fortunate to have him as a friend for many years, and I'm constantly impressed and inspired by his wisdom in the things he does.


BRUTAL ASSAULT
Elgin man left with serious facial injuries after horror attack by ‘group of men’
by Justin BowieAN ELGIN man was left with serious facial injuries after he was attacked by a “group of men” in the early hours of this morning.
The 56-year-old was taken to hospital after the brutal assault on High Street at 2am.
Cops have now made an appeal for any witnesses who can help to come forward.
They say a number of people would have in the area at the time.
And they are particularly interested in speaking to a woman wearing a red dress or jumpsuit who may have seen the horror attack.
Sergeant Phil Wu of the Divisional Alcohol and Violence Reduction Unit, Elgin, said: "From our enquiries so far, we believe that there may have been a group of men in their 20s involved in the assault.
“A number of people would have been in the area at the time and we are particularly keen on speaking to a woman wearing a red dress or jumpsuit who may have witnessed this assault.
“If you have any information relating to this incident please contact police on 101 quoting incident number 0504 of 17 November 2019.
“Or alternatively, call Crimestoppers on 0800 555 111 where information can be passed on anonymously.”
We told earlier this week how a teenage thug stabbed another schoolboy after a row about Snapchat messages.
The 15-year-old boy knifed his 13-year-old victim during a school lunch break in Glasgow’s southside.
The attacker fled the busy street leaving the injured boy stricken on the ground in March this year.


The Email Chic
In all likelihood, you have heard of Electronic Mail, but I’ve noticed that much of our audience (and 18-25 year olds in general) have been consistently estranged from it, despite its prevalence in news media. Perhaps it’s not immediately evident as the coolest thing, but if “staying informed” and grass roots-ing brands are still as hip as they appear to be, email newsletters should soon become so groovy that you’ll begin leaving the house for a down-the-street coffee shop just to be seen reading them.
Welcome to the wonderful world of aggregation.
In many ways, email newsletters are the antithesis of (and medication for) Facebook’s school of ruminate aggregation. You know – the doctrine that will forever be remembered as the original intellectual catalyst for the downfall of human civilization. The skimming and the jumping… how many Facebook users could I fool by simply sending featured images, headlines, and abstracts for social cards without any hyperlinked destination? Could I manage to get Donald Tump elected President of the United States by way of Scrolling Hypnosis, alone?
Staying informed is a habit of time-honored traditions. Gramps has stopped by Bill’s General Goods every weekday morning for twenty years with a handful of change because The Sleepyville Monitor is a part of his identity – dependent upon- and accountable to his trust. We’ve continued into 21st century news media as if a digital equivalent of his readership would be so difficult to fathom that legacy publications are best-off forcing the standards of print onto the web instead of investing in research/experimentation, which is why the fucking New York Times still sends your handset away to a separate mobile version of their site – a horrible remnant of browsing from the oughts that’s rarely seen on blogs, these days, much less on properties of titanic news powerhouses.
For whatever reason, most of the industry has behaved as if Grandpa’s sort of routines no longer exist in day-to-day life, but – if anything – our Automated Hell is vastly more saturated with them, no?  I, myself, am considerably proud of my ~60,000 unread emails, and I’ve conceded to the vast majority of the popup opt-ins I’ve encountered since shortly after our launch because I rarely found myself visiting/reading undesirable web.
“I don’t email” is a sentiment I hear from young people often, which is perfectly fine. I don’t vote!
If it’s true that “nobody wants that,” nobody should be participating in the democratic process. Yes, I’ve experienced the no patience for more than 300 words phase of life, and I understand wholeheartedly the desire to retreat forever from it all. I would much rather exist in an old, open farmhouse with a wife, a garden, no internet, dusty old literature, and two ancient Bentleys than spend all my time crafting mirages in a black mirror, but neither cowardice nor negligence are options for us, right now. This country doesn’t have room for any more.
That’s not to say that you should be expected to read 6 hours of news a day – it’s the media’s (our) job to maintain our own accessibility, and for this, daily/weekly newsletters are an unbelievably effective method. The meta-aggregators in today’s industry are often paid exclusively to ease your digestion, both independently and by mastheads.
Dave Pell is a superb gateway from the former – an aggregation legend. His daily correspondence – called NextDraft - is more often than not the ideal front page of the day.
I’m asking those of you youths yet without your own reading habits to trust my taste – if not my authority – and explore some options from my own inbox.
Ultimately, you just can’t replace a legacy die-hard-news shop for a good political briefing. The POLITICO Playbook is the most time-efficient way to keep up with U.S. and World politics as you walk about your life, and many of The New Yorker’s newsletters are a great longform, much more visual compliment. For a slightly less-chaotic, but still relatively unproven alternative to the former, try Axios AM.
National Geographic may seem a bit old guard, but has remained a consistently excellent photographic publication. Its print edition has no place but on the poll in tangible media subscription terms, but it has been quite depressing, as of late. Turns out, we’ve made quite a dystopia for ourselves, and their ability to encapsulate the world can be overstimulating, at times. If you’d like a bit more control – or are uncompromisingly digital-only – its web edition has matured quite competently, and is elegantly parsed by their newsletters. (You’ll need to create an account, if you don’t already have one.)
It’s no secret that Medium has been on the decline, lately – and it’s always required a particular sort of tolerance – but The Daily Digest still delivers a few important essays, occasionally. And of course – there are options by regularity and topic, which you can fiddle with here when logged in.
On the more innovative end of the industry, there’s The Outline’s newsletter, which – being the property of a more deliberate, gorgeous, open-web publication – is a bit underwhelming, but then again… why aren’t you just looking at the site, anyway? The Pudding’s output may be sparse, but – again – just… look at it. I can’t claim to have made much use of the information presented in their gorgeous visual essays, but it sure is fascinating.
The Verge’s Command Line is often so clever, it can almost make tech news engaging. (Our very own The Tone is directly modeled after it, visually.)
Then there’s War Is Boring - a tactical/tech news site? I recently discovered. “From drones to AKs, high technology to low politics.” I wouldn’t describe it as a primary read for me, but it’s still nice to see what the Big Boys are up to, once in a while. (I am mostly just waiting attentively for the U.S.S. Iowa to be put up for auction.)
 After an excellent few years of playful indulgences, the project now has a whole DweebNet with a newsletter that always fascinates, if a bit dryly. What did you expect?
The Poetry Foundation can also be easily convinced to send you their Poem of the Day, and biweekly newsletter.
And finally… the meta media folks.
Columbia Journalism Review’s always the prettiest to look at when it comes to coverage of industry, and their squeaky-clean perspective won me over quite quickly. They send their ultra-clean, editor-compiled Weekly Highlights every Thursday. The American Press Institute’s list isn’t a bad idea, either. Then, of course, there’s Harvard’s NiemanLab, which offers afternoon and Saturday morning emails. All three often cite the Pew Research Center, which offers its own palette of email lists, should you find yourself hungry for d a t a. Though, I do not, and I enjoy them.
Landing on the “homepage” of even the most familiar online publications can feel daunting and impersonal, but having an authority on the industry (hopefully, with some sense of humor) parse the torrent and deliver it unto your personal inbox can ease the reading process into a much more intimate, sensical, enjoyable, and productive expenditure of your valuable time.
For a publication of our scale, the routine of a newsletter can act first as a simple reminder of our existence, and mature into a way to reach out directly to our audience in a distinctly magazine methodology – one which pervades a real, consequential relationship with consumers.


Green Screen Effect
- Green screen basically lets you drop in whatever background
images you want behind the actors and/or foreground.
- Corresponding image shows how green screen can be
maupulated to make different backgrounds.
- Upload your image with GREEN-BACKGROUND below and
try adding some amazing background to it.
- Try it now!


Film title:
The Emigrants
A Better Life
America America
Crossing Over
Gangs of New York
Golden Door
The Immigrant
The Visitor
Amreeka
Dirty Pretty Things
House of Sand and Fog
The Border
The Godfather: Part II
...And the Pursuit of Happiness
An American Tail
Avalon
Bend It Like Beckham
Dancer in the Dark
Fast Food Nation
Green Card
Heaven's Gate
Immigrants
In America
Sin Nombre
Terraferma
The Glass Wall
The Other Side of Immigration
The Perez Family
Ali: Fear Eats the Soul
An American Rhapsody
Babel
Black Hand
Bread and Roses
El Norte
Est - Ouest
Flores de Otro Mundo
Frontera
Goodbye, Miss 4th of July
Illegal
L'ange de goudron
Las cartas de Alou
Moscow on the Hudson
Spanglish
The Harvest/La Cosecha
The Italian
The Namesake
The New Land
The Swissmakers
Under the Same Moon
...And the Earth Did Not Swallow Him
A Day Without a Mexican
Across the Sea of Time
Almost a Woman
Amanecer
American Harvest
Anchor Baby
Angela's Ashes
Beautiful People
Beyond Our Dreams
Biutiful
Black Legion
Bolivia
Border Cop
Border Incident
Bread and Chocolate
Brick Lane
Bride Flight
Broken English
Brooklyn
Citizen USA: A 50 State Road Trip
Ellis Island
Espaldas mojadas
First Snowfall
From the Edge of the City
From the Other Side
Frozen River
Gaijin: Roads to Freedom
Head-On
Hester Street
I Love Vienna
Im Land meiner Eltern
In This World
Inch'Allah Dimanche
It's a Free World...
Junk Food
Katzelmacher
Lonely in America
Lucky Miles
Machete
Made in L.A.
Man Push Cart
Mao's Last Dancer
Monsieur Lazhar
My Beautiful Laundrette
My Boy
Northless
Princesas
Romance in Manhattan
Safrana ou le droit à la parole
Samba
Scarface
Silver City
Sorry, Haters
Stranger Than Paradise
The City
The Elevator Operator
The Girl Who Spelled Freedom
The Godfather
The Hand That Feeds
The Man Who Cried
The March
The Romanians Are Coming
The Secret of the Grain
The Terminal
Three Colors: White
Vesna va veloce
West Side Story
Covers by genre
western
1
short
1
romance
16
music
3
flim-noir
3
drama
95
documentary
8
crime
20
comedy
22
biography
3
animation
1
adventure
7
action
5
Covers by genre colors predominant palette
western
short
romance
music
flim-noir
drama
documentary
crime
comedy
biography
animation
adventure
action
#865846
#f5621f
#d6a586
#f5e7ce
#2e1e15
#80593c
#c9955d
#efdb93
#543227
#399da8
#cf9563
#e2e2d5
#422219
#dc3b17
#bb8e62
#efddc6
#3e2726
#c33b31
#dbc535
#cccdc8
#4a2a24
#4e8b93
#d6955e
#e4e4d8
#dad0c3
#2d292d
#b75c40
#259dbd
#2c2727
#A44f3a
#bd9e79
#d7e1d9
#302B2f
#995f50
#cca179
#cfe0d8
#314A44
#D33c1A
#E49B5E
#C3d6ce
#30384B
#CC492C
#EF9F57
#CAC5C3
#2B3438
#14AFB8
#B4806E
#D5DACE
#27281F
#8B5D44
#D39968
#C8D6C6
Luminance by genre
western
short
romance
music
flim-noir
drama
documentary
crime
comedy
biography
animation
adventure
action
61
59
56
49
52
55
48
51
53
52
51
54
50
Diagram Stats
photomontage: 39%
44 films
mozaic: 20,3%
23 films
single photo: 40,7%
46 films
Type of Image Stats
photography: 82,3%
93 films
Illustration: 13,3%
15 films
combined: 4,4%
5 films
Etnic differences Stats
yes: 26,5%
30 films
no: 73,5%
83 films
Relational Stats
person: 38,9%
44 films
place: 22,2%
25 films
both: 38,9%
44 films
Kinesic Stats
facing: 53%
60 films
backwards: 6,2%
7 films
profile: 12,4%
14 films
combined: 23%
26 films
not applicable: 5,4%
6 films
Gender Stats
male: 29,2%
33 films
female: 15,3%
17 films
both: 46,6%
53 films
not specified: 8.9%
10 films
Note 1:
From the total of 120 films, the cover analisis misses the followin films due to lack of information: Annie was a wonder, Ospiti (guests), Im Land meiner Eltern, The elevator operator, The March, The Romanians are coming and Unnatural causes.
Note 2:
For the correct use of the category filters, we beg you to turn back off each item category used, before closing de category. If something is going wrong, verify there are all items from all categories -off- and click "reset filters" until all covers are -on-.


--- title: Shipping / Delivery hero: Delivery Details ---
Please review the below information to find answers to any of your questions regarding our policies and order services.
Shipping Services
Yash Farm to Table provides Produce delivery to your orders via Whatsapp, telegram or Signal application. You can email us directly your orders, questions and suggestions to<EMAIL_ADDRESS>or<EMAIL_ADDRESS>The delivery time frame may vary due to service delays, holidays or extreme weather situations, Covid-19 restrictions etc.
आपण आपली Order देऊ whatsapp or Switch or Telegram शकता. फळे तथा भाजीपाला हा आपणास घरपोच केला जाईल. आपल्या आर्डरची नोंदणी सोपी होण्यासाठी काही सूचना जरूर वाचा.


--- layout: post date: 2012-03-05 time: "12:00:00" authors: ["Greg Wilson"] title: Programs as Experimental Apparatus favorite: true tags: ["Content"] ---
Suppose you have two photographs of a patch of the night sky:
and you want to know how different they are. The simplest way would be to see if any of the pixels' values differ, but that's pretty much guaranteed to return a "yes". A better measure is to see how many pixels differ by more than some threshold, but that raises two questions:
To answer the first question, most images encode the red, green, and blue values of pixels separately, so we can add up the absolute values of the differences between those color values:
d1 = abs(R — r) + abs(G — g) + abs(B — b)
We could equally well add the color values for each pixel to get a total, then look at the differences between those:
d2 = abs((R + G + B) — (r + g + b))
Does it matter which we choose? And either way, how big a difference should count as different? Since we're scientists, we can answer these questions experimentally. Here's a Python program that reads in an image, scales it down to half its original size, scales it back up, then calculates both difference measures. Its output is a histogram of how many pixels differ by how much according to the two measures, and how different the measures are from each other:
import sys from PIL import Image # Load the original image. original = Image.open(sys.argv[1]) width, height = original.size original_data = original.load() # Create a duplicate by enlarging then shrinking the original. duplicate = original.resize((width/2, height/2)).resize((width, height)) duplicate_data = duplicate.load() # Count how many pixels differ by how much using two measures: # | (R+G+B) - (r+g+b) | # | R-r | + | G-g | + | B-b | overall = [0] * (3 * 255 + 1) individual = [0] * (3 * 255 + 1) for x in xrange(width): for y in xrange(height): o_r, o_g, o_b = original_data[x, y] d_r, d_g, d_b = duplicate_data[x, y] diff_o = abs((o_r + o_g + o_b) - (d_r + d_g + d_b)) overall[diff_o] += 1 diff_i = abs(o_r - d_r) + abs(o_g - d_g) + abs(o_b - d_b) individual[diff_i] += 1 # Display histogram. num = width * height print '%10s %10s %10s %10s %10s %10s' % \ ('diff', 'overall', '%age', 'individual', '%age', 'difference') for i in range(len(overall)): pct_o = 100.0 * float(overall[i]) / num pct_i = 100.0 * float(individual[i]) / num diff = abs(overall[i] - individual[i]) pct_d = 100.0 * float(diff) / num print '%10d %10d %10.1f %10d %10.1f %10.1f' % \ (i, overall[i], pct_o, individual[i], pct_i, pct_d)
Its output looks like this:
| diff | overall | (%) | individual | (%) | difference |
| 0 | 130716 | 42.6 | 128472 | 41.8 | 0.7 |
| 1 | 6574 | 2.1 | 1746 | 0.6 | 1.6 |
| 2 | 9432 | 3.1 | 8430 | 2.7 | 0.3 |
| 3 | 63792 | 20.8 | 66992 | 21.8 | 1.0 |
| 4 | 4887 | 1.6 | 7037 | 2.3 | 0.7 |
| 5 | 4880 | 1.6 | 5692 | 1.9 | 0.3 |
| 6 | 29115 | 9.5 | 29622 | 9.6 | 0.2 |
| 7 | 3131 | 1.0 | 3485 | 1.1 | 0.1 |
| 8 | 2888 | 0.9 | 3175 | 1.0 | 0.1 |
| 9 | 13714 | 4.5 | 13907 | 4.5 | 0.1 |
| 10 | 1981 | 0.6 | 2097 | 0.7 | 0.0 |
| 11 | 1849 | 0.6 | 1955 | 0.6 | 0.0 |
| 12 | 7597 | 2.5 | 7665 | 2.5 | 0.0 |
| 13 | 1432 | 0.5 | 1467 | 0.5 | 0.0 |
| 14 | 1311 | 0.4 | 1341 | 0.4 | 0.0 |
| 15 | 4608 | 1.5 | 4641 | 1.5 | 0.0 |
The good news is that there isn't much difference between the counts for the two measures. However, it's hard to get a sense of what else is in this data. Time to visualize—let's plot the percentage of pixels that difference according to d1:
The result isn't surprising: if our upsize-downsize algorithm didn't lose any information, we'd expect no differences at all. Since rescaling is lossy, though, we see that a lot of pixels differ by small values, and only a few by large values.
But there's something else in our data that could easily be missed. Look at the first dozen entries in the table above; do you see a pattern? Let's plot the scores for multiples of three separately from the scores for differences that aren't even multiples of three:
If we do the same thing for the whole data set, we get:
A moment's thought produces a hypothesis: since we have three color channels (red, green, and blue), it's possible that the rescaling algorithm is introducing a systematic bias by perturbing each channel by one as it sizes up or down. Looking at the curves for differences up to 15, that bias seems to be responsible for most of the overall difference. If we really want to measure the differences between images, we're going to have to find a way to eliminate this.
I'm not going to go into how we might do that now. What I want to point out is that this is not a new problem. Think about the telescope that took the picture we started with. Glass lenses are subject to chromatic aberration; telescope designers must either reshape lenses to minimize it, combine layers of different kinds of glass to correct for it, or tell the astronomer to compensate mathematically somehow. Equally, we can implement a different resizing algorithm to remove this systematic bias, or correct for it. The important thing is to think of a program as a piece of experimental apparatus, and treat it accordingly. That is part of what we want to teach in this course.


‘I’m sorry we let you down’ – Arsenal star issues apology after Unai Emery sacked by Gunners
by Ron CarneArsenal goalkeeper Emiliano Martinez has apologised to Unai Emery and his staff after they were sacked by the club on Friday.
The decision came amid a seven-game winless streak for the Gunners across all competitions, as they continue to struggle to show that they are capable of breaking back into the top four.
SEE MORE: ‘Let’s get to work’ – Ljungberg delivers message to Arsenal fans after Emery exit
Currently down in eighth place and eight points adrift of fourth spot, the Arsenal hierarchy decided that the time was right to make a change on the bench, with club legend Freddie Ljungberg taking temporary charge as interim head coach ahead of the clash with Norwich City on Sunday.
While Emery undoubtedly had his faults, the players will need to take responsibility for the poor performances and results too, and Martinez has held his hands up and apologised, as seen in his tweet below.
The shot-stopper also said sorry to his now former goalkeeping coach, and it’s a gesture that will most likely be appreciated by the former Arsenal boss and his staff.
However, it doesn’t change the reality of the disappointing and frustrating season that Arsenal have experienced so far, and so time will tell if firstly Ljungberg can get a positive reaction from the players, and then who the permanent solution will be for the north London giants.
For now, the headlines continue to be dominated on talk of Emery’s tenure, while it remains to be seen if any other Arsenal players come out publicly to address his departure from the Emirates.


Receive the best possible deal , and in the no time.. Check for the closest option and finalise the deal with ease.. Also have a satisfying experience shopping with us..
Learn More
{{ error[1] }}