The LiveCode community is vital to the success of our platform. We want to ensure the community voice is heard loud and clear. To this end, we approached a leading and respected member of the LiveCode community known for his outstanding contributions and for his extremely successful LiveCode built apps.
We asked Trevor DeVore, Director of Technology at ScreenSteps if he would like to interview Kevin & Mark, asking all the questions that he might have as an active LiveCode community member. Trevor kindly agreed and came up with some excellent questions which we are sure will be of interest to a wide audience!
This was without question the biggest risk that we’ve ever taken, bar the one we didn’t take – the risk of not doing it. As the longest standing platform in our class we were weighed down by a creaking architecture and lagging feature set. I know the community celebrated after the campaign, and it’s true I took a moment out to celebrate. However from the moment the campaign closed, the success was tempered for me by a pressing awareness of the challenge involved. I was well aware of the corpses of technology companies throughout history who had tried this and failed. We put our foot very firmly on the accelerator. We had raised as much money as we could through crowd funding and we started to leverage that major success to raise additional funds behind the scenes. We sold a chunk of equity and successfully brought in substantial matching government funds. Crowd funding certainly helped enable all of that.
We had four huge challenges. Firstly was the matter of the pre-announcement. Pre-announcements are necessary in crowd funding but tricky when you have ongoing revenues from a product. You only need to look at the Osborne effect for a good example. We had just made the largest pre-announcement in our history. The post crowd funding period had a negative impact on our revenues because of this.
Secondly and also related to revenue, we introduced the dual license (adding the open source Community Edition) relatively early in the process. One thing we could perhaps have done differently with hindsight, might have been to go open source with the launch of 8. It is always going to be hard(er) to contribute to the core engine, and the modular LiveCode Builder that we intended as the primary means for people to contribute useful features with only came into being in 8. And in the meantime 76% of the user base gradually moved to the open source version, yet the user base growth intended to offset the revenue drop required the deliverables. I also wonder with hindsight whether we could have saved a little time by not releasing 7 at all.
Thirdly, the scope of the project was the largest we had ever undertaken. To raise the difficulty bar here even further, we hired new engineers who had to be trained with no previous experience of our engine. Their immediate and massive task was to undertake some extremely complex refactoring. Over the course of time our team, new and old, got tested in the fires of this project. We refined our processes, streamlining the way we manage, test and release throughout.
Finally, as we went through the project we found a lot of bodies buried in the code. The code base is old, some of it going back to early 1990s Unix. The projects grew in scope and some of the scope was vast. There were days I would wake up to find that an engineer had “discovered” an extra 3 months work that day. No kidding, that literally happened! We’re decent at estimating well defined projects, but some of this creep was “how long is a piece of string”. I was reminded of the difficulty that Allegiant had back in the day porting SuperCard to Windows, a project that ultimately was a major contributor to their demise. We developed various techniques to try to address these issues, such as comparing a project size with others that had gone before and talking to project leaders elsewhere who had done projects approaching this complexity. But some of this stuff you can only learn by doing and we just had to keep going. In the end only 3% of our code wasn’t moved or touched in some way. Not to mention that we wrote and introduced an entire new language – LiveCode Builder.
As our CEO I feel like I have come to the end of one of the most challenging periods I’ve ever had in business. One day perhaps I’ll tell the story of everything that went on behind the scenes to keep the ship sailing throughout this period. There were many sleepless nights, a lot of negotiating and most of all, sheer unyielding determination. Failure was not an option. Changing course was not happening. And in spite of the costs and the challenges, we got it done. For the moment suffice it to say that I personally will not choose to lead a project of this sort again any time soon.
We are all incredibly proud of the result. We have a platform we can make changes to very rapidly. When we pull off Infinite LiveCode and keep refining LCB the number of features in the platform that both us and the community can create and the speed that happens at, is going to be incredible. I do not believe anyone will recognize LiveCode or the strength of our ecosystem a year out from today.
Here is as complete a list as I can make it, roughly in chronological order, with the colorization showing what is in all editions including Open Source (green), what is in Indy and Business only (blue), and what is only available to Business (black, bold). Additionally, the items in italics were purchased from a third party, incurring a cost to us.
Very first Open Source edition available. Optimised image performance. Image caching. Autocomplete in the message box. Source – The put command in LiveCode outputs content to the message box. The source button loads the script editor and selects the line of code that output the content. New project browser puts in its first appearance. Before and after handlers for behaviours. Relayer command introduced. Field improvements – support for Non-BMP unicode characters, hexadecimal HTML entity references, strong and em HTML tags, a new listIndex paragraph property and a new metadata paragraph property. Effective rect of stack – get and set the rectangular area of a given stack with its decorations and frame taken into account. Import/export snapshot at size – resize your snapshot before importing it into your project. Control at location – get the control at a given location. Split and Combine variants – enables better handling of data in an array. Object selection started/ended – lets you know when a user starts and finishes dragging over an object. Chained behaviours. Locking group updates, the effective visible objects, removed need to activate LiveCode Community. iOS 7 support, Better quality printing on Mac. Resolution Independence. Scaling regardless of size or aspect ratio of screen for mobile platforms. High density supported. New Graphics layer, density mapped images, multiple density support. Improved image editing tools. Server Graphics support. PCRE library updated. libUrlSetSSLVerification supported on all platforms. New colorDialogColors property added. revFont external integrated. Enhanced Filter command. Text Measurement. Recursive arrays. Xpath functions added. Default font settings from IDE. Resolution Independence for desktop and retina screens. SSL and encryption support added for mobile. Assert command added. HTTPS through proxy, Image Filtering Updates, iOS 7.1 Support, SQLite update, Stack Scale Factor, Hashbangs recognized in LiveCode Server. Cocoa support mobileLocationAuthorizationStatus added. Multimedia support on Mac uses AVFoundation. iOS 8 support. Non executable file redirection on Mac. New global property to identify engine version. Threaded rendering. Nine Way Stretch for images. Updated text rendering for speed. Export snapshot with metadata. New variants of open and secure sockets. Multiple density image support for patterns. In-app purchasing extended for Amazon and Samsung stores. Clipboard data styled text added. Improved revBrower with CEF added. Javascript integration. Unicode, it just works – quite an array of subfeatures related to this. New Graphics library. Screen regions – only redrawing areas of screen that have changed. Icon gravity. The effective points of a graphic object added. LiveCode Server graphic support added. Raspberry Pi (community supported). Native 64 bit Linux and Server engine. File format changed to support unicode. Changes to initialisers for constants and locals. Specify the text encoding of a server script file. bidiDirection function introduced to expose the engine’s implementation of the Unicode Bidirectional Algorithm. Unmask property enabled on Mac OS X. Sort cards of background now throws an error.
mobileLaunchData function. The commandName and the commandArguments. Mobile Sockets. Objects are deleted more frequently (and not just on idle). Advanced Camera features on Mobile platforms. Application Transport Security (ATS) disable check box added. Android Hardware Acceleration added with option to turn on or off. Added launchDataChanged message on Android. Added beta testing entitlement to iOS apps standalone settings. Ability to set the dontUseQT property for a player object (Windows and OSX). Play background audio on iOS. New “mirrored” property for the OSX player. New ‘readyForDisplay’ ios player property. Windows default videograbber is now DirectX. Xcode 7.0 support added. DataGrid added to the Standalone Settings script libraries list. Ensure ‘the effective rect of stack’ is more accurate on Linux. Installer no longer required on OSX. Make filenames with accented characters appear correctly in the detailed files on Mac. HTML5 deployment. LiveCode Builder. Widgets: Browser, Navigation Bar, Tree View, Clock, Header Bar, Line Graph, Segmented Control, Switch Button, SVG. JSON library added. Widget Utility Module. More powerful Clipboard access. 64-bit Mac standalone deployment. SSL support for PostgreSQL connections. “Find and replace” that preserves text style. Optimised Unicode text processing. Unicode printing on Linux. Greatly improved native theming on desktop platforms. A new IDE Start Center and interactive tutorial. MergEXT extensions added: JSON, Accessory, FTPD, Social, ZXing, Map Kit, Doc, Banner, AV, Pop, CL, Settings, Dropbox, Reader, BLE, AES, Notify, MP, BgTask, NIC, Bonjour, AWS, GK, Socket, LA, Button, Google, AnswerColor, Device, Markdown, Microphone, Screen, Blur. PDF viewer. Business Application Framework.
Feature differentiation is essential. We know that the dual license only gets us part of the way to a sustainable ecosystem. For example, many of our larger, successful commercial customers with high support needs and technical requirements only use the software in-house. They want us to continue to invest heavily in the platform.
We have a few broad rules we use to help us decide. Firstly, our goal with OSS is to create a good solid core platform. So any feature that we consider to be “core” should go into all editions. That includes things like changes to the language itself. Next, OSS is intended to be extensible so the core refinements to LCB to allow this extensibility (that we’re talking about in this campaign) should go into it. Next, OSS is not and never will be crippleware. Its got to do what it is capable of well. So if features are broken they need to be made to work. When it comes to the paid licenses, we look at things that generally speaking help to round out more commercially oriented apps or apps with particular corporate value. Improvements that enhance performance, access corporate information systems or support concurrent connections would be good examples. Bolt ons that tend to be incorporated in apps that go into the app store make sense here. And features that aid in teams designing larger and more complex apps in LiveCode, such as with the Business Application Framework generally will go into paid editions. The final consideration here is if we’ve had to acquire the rights or pay licensing fees on a component. Those sorts of things will generally only go into the paid editions.
It is a tricky balance and in order to get it right we engage in a lot of debate internally. We have a team member who plays the role of open source advocate and on the other side we have all the business requirements. Our goal is to create a thriving ecosystem with as many people using LiveCode as possible, and with those that derive commercial value from it providing fair income to us in some form or other.
I think this is also a very relevant question for widget authors to consider when creating a component. Rather than simply dual-licensing it, I would urge those who intend to create a commercial revenue stream to consider splitting the feature set and providing a gradual increase between editions.
Everything we’ve done since the original Kickstarter and the move to the dual license and OSS has been about growing the community. The model has been that we monetize a smaller slice of a much bigger pie. This business model is used in various forms with great success across the industry. It is the right model for a platform like LiveCode, providing something for the wide variety of types of user for a platform like ours. Network effects are critical, code and knowledge sharing are what make and break our platform.
The length of time it has taken to get to version 8 has made this a challenging transition for us. The primary challenge during that period has been to grow the overall pie faster than users move to the Community Edition. It’s not something we’ve got right yet. Infinite LiveCode is absolutely critical in helping here. There is no single thing we could do that would help us to grow the user base faster than Infinite LiveCode. Free open source extensions will attract new users on the open source side. And with the forthcoming extensions store improvements we will also provide a neat one stop shop built into the platform and a revenue share, for those of you that choose to build commercial extensions. That will help us to build commercial revenues.
As it stands, to add system provided features to LiveCode requires the use of Java/Obj-C/C/C++ – either by adding support for things direct to the engine, or as an external. Indeed, in order to add support for a particular feature relying on foreign API a lot knowledge needs to be acquired – you first have to work out how to use them before you can even think about working out how LiveCode might interact with them.
Infinite LiveCode means that Builder can be used to add features which use system and third-party APIs and, perhaps most importantly, this can be done externally to the engine – as loadable modules which don’t have to be part of the core source tree. Furthermore, these features can be done from one language – Builder – and without requiring native toolchains for all the platforms you want to build the feature for.
Not only will this approach mean the core LiveCode dev team can be more efficient at adding features to LiveCode, but it also means that third-parties can also do so with a great deal more ease than is possible at the moment. In particular, we hope that third-parties with intimate knowledge of particular foreign APIs will be able to use Builder really easily to bring their functionality to LiveCode.
Our hope is that, over time, the core LiveCode dev team can focus much more time on supporting, maintaining and evolving the core architecture, rather than a very broad range of specific features.
The aim of Infinite LiveCode is to solve the problem of language interoperability by splitting it into two pieces.
The first piece is the unsafe module. This will be a Builder module which contains all the very lowest-level pieces you need to write glue code which wraps a low-level foreign function in a high-level Builder handler. Hopefully this should make wrapping any foreign function possible – although not necessarily easy!
The second piece is the tool we intend to write which takes a high-level description of a foreign API and writes the glue code automatically for you. Now, Java is a pretty homogenous language in terms of the patterns you see in its class hierarchies so our initial analysis has indicated that we should be able to wrap Java APIs almost completely with the first iteration of the tool (I won’t rule out the possibility that we might miss some patterns in the first version – there are a lot of classes in the Android SDK). A similar thing appears to be true of Objective-C too (as least as far as Apple’s use of the language goes). When we look at C, however, things are quite different – two different libraries can have wildly different conventions and the more esoteric ones might require evolution of the glue generation tool to be able to support. So, the plan with C is that we’ll start with ensuring you can wrap libraries which use the most common conventions on each platform whose APIs are C (and Objective-C) based.
Some aspects of interacting with foreign functions will require Builder utility functions to be written – hooking into Objective-C notifications, and Java listener patterns are a good example here. We’ll add these as we evolve the auto-generation tool to cover these sort of patterns as we find them.
You are going to be able to wrap a truly vast range of external libraries from the outset with the core Infinite LiveCode goal. That said, there are a few things which might require further engine and Builder infrastructure related work. For example, we have not included in the initial version of Infinite LiveCode (as yet) the ability to run Builder code on an auxiliary thread – this will need some work on the Builder VM, and then significant care to do until we can bring multithreading as a native feature to Builder. If there is scope to add a few more stretch goals to this campaign we may do so, otherwise we may have to consider coming back to these things later.
You will be able to create a single widget library which runs on all platforms. We’re intending to make it so that a single extension can contain multiple Builder modules, and allow a module to be marked as being intended for a specific platform. This gives a couple of options for implementing cross-platform extensions.
The battery monitoring example published in a recent blog post uses the simple approach – it uses separate (distinct) Builder modules for iOS and Android but with the same set of public handlers (which are what LiveCode Script sees).
The other approach is to implement the library module (i.e. the set of public handlers which LiveCode Script sees) once, and then implement a set of lower-level handlers which it uses for each platform. Each of these sets of lower-level handlers would be specific to each platform. This is more complicated but has the advantage that an API can be exposed to Builder as well as to Script. For example, it wouldn’t be too hard to restructure the battery monitoring example in this fashion, which would allow a battery status widget to be written without it having to resort to calling into LiveCode Script.
Yes – native layers allow you to add third-party ‘views’ (technically a View on Android, UIView on iOS, NSView on Mac, HWND on Windows and XWindow on Linux) to a stack’s window. The browser widget uses this feature, for example.
The native layer feature can be used to wrap any third-party (or system) component which provides its functionality as a view. For example, one of the worked examples we propose to construct if the final stretch goal is met is a widget which wraps the native input field on Android and iOS – this will make this native mobile control as easy to use as the browser control now is (compared to using revBrowser, or mobileControlCreate before).
This gives easier access to a wealth of system and third-party defined controls on all the different platforms we support.
It is very much the intention that Widgets v2 will render the old Externals API obsolete.
At the moment you have to write your external handlers in C in a special way to allow them to be used, so much of the work of writing an external is writing such a bridge between how LiveCode wants your external handlers to be structured and how the lower-level functionality wants to be used.
As Builder will be able to bind to C (and other language) APIs in a way closer to how they work, you won’t have to write this bridging code yourself – you can concentrate on implementing the higher-level abstractions needed to wrap the foreign code and make them accessible from LiveCode Script.
Of course, I’ve not mentioned performance yet! As it stands Builder is not yet fast enough to do computationally intensive work, so yes, for some applications you will likely find that writing the core routines in C and then binding them to Script via Builder is the best approach. However, one of the widest uses for Infinite LiveCode is being able to easily access features exposed by the platform via system APIs and third-party libraries and in this case the performance of the code you write in Builder is less of a concern as it will be dominated by the work occurring in the foreign code.
We are committed to making Builder run really fast in the future. However, right now our focus is correctness and ability; rather than speed.
We’re pragmatists and we are ambitious. We had a choice when 8 was out of the door, to sit back and gradually make these changes over the course of yet another year, or to go out and see if we could fund doing them now. If there is one thing I’ve learned looking back over all the years of doing this, it is to be even more ambitious and to do everything possible to deliver more, faster. That is particularly true having come through the spectacularly challenging 8 project. Having come through it, my motivation to simply sit back and not do everything possible to move us forward rapidly is about zero! The amount of effort needed on top of what we’ve done is small in comparison to what has just gone in. Yet that thin layer on top is where the magic happens, where the features get made, where the community gets truly enabled.
This campaign is about providing a choice. There is no obligation to fund this or any other campaign. My reading on it is that many in the active user base are extremely keen to see us move forward as quickly as possible. And spread out over the user base as a whole this campaign doesn’t to have to be a big ask each. It also gives our open source user base the opportunity to contribute a little to the platform along with our subscribers. At the end of the day, if we don’t ask we certainly don’t get! We are providing a choice, an optimistic choice, an ambitious choice and we think it is the right one.
I expect that crowd funding is going to be used quite a bit for the foreseeable future for the same set of reasons. We will aim to spread the campaigns out. Our goal is ultimately to rebuild a stable subscriber base and services revenues that allow us to sponsor more features in the core platform without having to run as many campaigns. In the mean time we’ll keep talking to you about what you want, and do what we can to provide you with the option to deliver it. That also has the advantage we know each time how important something truly is before we do it.
What great questions, and really interesting answers! We hope you agree. Thank you Trevor for getting involved.
We have seen so much positivity over the last 6 days around Infinite LiveCode. Thank you. It is clear that this is the right step forward for the LiveCode community and the LiveCode platform, and what the majority of you really want to see us doing next. If you believe in what Infinite LiveCode can bring, please pledge today. We want to do this now and we want to do this right. Let’s reach $70k by Monday and deliver Infinite LiveCode with great reusable examples, this summer.
Join the conversation