 Okay, I'm ready to start if you are. Yeah. So good morning, everyone. I'm Thomas Cohen. I work at the Samsung open source group. I'm based in London, England. Today I'll be talking about EFL, UI toolkit designed for the embedded world, which is essentially what I've been working on at Samsung for the last seven years and a few years before that on my spare time. And this is it. If you want, that's a link to the slides. So if you want to get them or QR codes, scan it real quickly if you want. If not, it's available on the website as well. On the ELC website. Okay. Again. So first let's start where we came from. So the Enlightenment project is very old. Actually way older than I was involved. So it predates GNOME and KDE and all of those, or some of those. So for example, maybe some of you remember back in the days before MetaCity, GNOME used Enlightenment as the window management. So it must predate GNOME. So it was initially a window manager for X and then it got split into libraries. So it was designed for that. But after that we made a general purpose for more application, more than just dialog menus or the rest of those, the requirements of a window manager. So essentially dates back like the split part to I think around 2000. Not sure exactly again before my time. And we targeted the embedded world since the beginning. So it's something, it's like a bit of a stretch of a, you know, of a statement because I don't know how available or around embedded was back then. But what I mean by that, we always targeted low power, low performance, more constrained devices. And one thing, another thing that actually I didn't write that we always wanted to have bling on those. So we're known for being very blingy on very low resources. So that's where we came from. That's where we started. And nowadays, oh yeah, I forgot about that one. So this is how we look. I don't know, maybe people remember. It's like we had shaped windows and this is circa 2001, I mean not the beginning, but as far back as I managed to find a screenshot. And we just were very funky and weird. Yeah, I actually prefer more minimalist approach than this. And thankfully that's what we are nowadays. So we're using many places and by major industry players, surprise Samsung as well. We focus still on embedded devices. So that again, that definition of embedded is still very much stretched like in this conference, for example. So I would consider my one gigahertz smartwatch, which I don't have, but conceptually as an embedded device. But also we have some, I don't remember exactly the name of the company, but one company did smart voltage meters that actually had one bit screen, so like black and white. I don't remember the rest, but something ridiculously small and nothing, almost nothing, a very small device. So we ran on those like the whole range. We are a mix of LG PL2.0 and BSD. So nowadays we link a lot of things together and we're going to amalgalate. Well, that's a tough one. So amalgalate everything into one binary at some point. So it's going to be even more tied and just become LG PL2.0. But that's still, I think, good enough for everyone. It's not GPL, so you can just use it in your software. So we have a three-month release cycle that we have been doing for the last few years, which served us well because it added reliability and, first of all, for all the distributions who want to package us. So now we're packaging more distributions and more up-to-date. And also it just made it easier for us to deliver quality software. So we have two months of development and then one month of a freeze period where we fix everything, hopefully fix nothing, but you know. And we actually have now continuous integration, which is something, an area we were lacking on for many years. And part of that, we also have used Coverti. So shout out to them for giving free open source licenses. It's like a static analysis. We used to use, I mean, I prefer, I would always choose the open solution over the proprietary one, but this really blows Clang Analyzer out of the water, especially when we evaluated it because back then Clang Analyzer didn't have state. Now there are other projects that keep it. So you would have a false positive, you'd market as such, and then you'd get it again the next run, which was just ridiculous. We do API and ABI checks. So you can be sure that we don't, we haven't removed any API, we haven't, we used the Linux Foundation tool for that. We haven't changed any enums. So you can be sure whatever you compiled will work, even if you're just blindly. You don't need to recompile everything, which is very important for an ecosystem like Tizen, which I didn't mention. This is where Samsung used EFL. It's a mobile operating system. So it's very important there because you don't want to force all of your app store to recompile everything every time you decide to do a minor update to your back-end libraries. And also we have zero compiler warnings with WOL, WXTRA, with both GCC and Clang. I mean, this changes sometimes. We have one until one of us follows it and then we have to zero again. I find this one almost as important as static analysis. I think that adds a lot of reassurance. I mean, every time I fix a warning, it's actually, it's usually a bug. Like it's really usually a bug just hidden or a bug waiting to happen. So it's really good to fix those and I trust projects that have zero much better. Clicker still works. So just some statistics. So the latest version that came out, I think a month ago, we had 105 unique contributors and 3,300 commits, which is, I mean, you know, I don't like flashing around like commit counts as a metric, but it still, it just shows there are contributors and there is active development still going on after all this time. And overall, we've had 50,000 commits by many, many, many contributors from all around the world. So it's still going strong. So I mean, now you know a bit what it is, but let's see what it actually provides. So first of all, we have general purpose library. So we're C, we write in C, which is very common in the embedded world. So we need to give some tools to provide some tools. And since we have very performance and memory usage oriented, we also have some tools to help you save memory that we use ourselves. So the first one is string shares. So in string shares what you do, instead, so we found out, like we analyzed all of our UI and we saw we have the word OK or cancel, let's say 50 times in a screen. And that for every button where it appears, it will appear on the button, on the widget, like it will have a duplicated string everywhere. So what we did, we essentially, it's behind the scenes, it's a hash table that returns the same token all the time that's ref counted. And that alone saves a lot of memory because all the strings are shared. But more so, what it gives, which we use nowadays, it makes everything much faster because we don't need to do string comparisons anymore. We just do pointer comparisons. So if we want to go on a list and see which one is the same one internally, we just get a token and then compare the pointer instead of the string. Does that make sense? Perfect. So that really, I love this one. This is actually one of my favorites of ours. So, again, a general purpose library needs to have lists and arrays and everything that C lacks. But the problem is that, if you go to computer science 101 and you ask someone how do you implement a linked list, so it's going to be a bit worse than what I'm going to give you. This is computer science 102 maybe. But you're going to create a structure like next, prev, last, I don't know, a pointer to the general data. But the problem with that, that means that every node in the list is going to be allocated, the data itself and the header. And that causes, first of all, fragmentation and also cache misses your walk and then you try to find it. It's hell like trashing the cache. But also, you waste another pointer, you waste another like the header of malloc. So what we did, we have a way to tell you to embed the list into your structure and you just put it first. It's a macro and then that solves both problems. So those are in-line lists, in-lines array. We have ways to do a copy and write which we use heavily inside. So again, in an object system, you think about like in a UI, you have all of this UI, you have the window and you have this container and then this box and then this widgets and whatever. And all of them in the core is the same widget. So they have the same structure which is generic EFL object and then the generic EFL widget. So a lot of structure, a lot of information that is actually shared across everyone that is usually the same. So in the same tree, you usually have everyone visible, everyone the same color which is just don't apply any overlay color and be, you know, visible like none, no, not just Lucent, sorry. So one opacity. So we found that it saved us a lot of memory and we are very obsessed about seemingly unimportant memory. So I went on a wild, wild chase. Actually I wrote a nice blog post about it that to find, I think we had like dirty memory pages. So cause for every application we had, we wasted I think a few, maybe 100K, maybe even less of just dirty memory pages. So not even heap. Just like when you load, just waste a few. And I was, I think I spent like two days chasing that. Yes, that one is, we care about those things. And we have magic checks. So we just have an integer in the beginning of every structure that is important that we expose and that has a magic number. So if you dereference the wrong kind of pointer, we'll find it very early and hopefully we won't set fault because the pointer would still be, you know, valid memory region just different. And we have, you know, all the basics. List, hash, red, black tree, whatever. We have a lot of things. Unicode. So, there you go. So we also have a binary serialization library. So nowadays, even surprising this conference, whenever you want to serialize something, it's XML or JSON for some reason. But we still, first of all, we've been doing it for a while. But also we found and we benchmark that JSON is really not that fast. I mean, you have to parse strings. They're like spaces. It's not always compressed. They're like a lot of things and also you need to validate. So when you have a binary structure, it's really quick to just serialize the C mapping, which is almost always the same. I mean, if you're in the same Indianess, same everything, which is common, it's going to be very fast. But we also support decompiling and recompiling from text. So it actually is the same for you as a user. So we do, and we also have a tool called ViEat. It is the name of the library. So we open it directly in your editor and then you can edit it and recompose it. So for everyone, for all intents and purposes, it feels like a text or a presentation, but it's passed ahead of time, validated ahead of time, and therefore it's much, much faster. And we can use memory map to load it. So for example, again, JSON equivalent, you'd have a base 64 encoded dump of data, which is the image. We just map the image, like bitmap, as it is. We support compressing and signing, so for whatever you need, maybe. Oh, my clicker really stopped working. So we do UI. So as part of a UI library, you need some extra fancy stuff, like a main loop. And also, when you have a main loop, you're tempted to add some more useful stuff, like timers, or animators in this case, which are timers that are aligned to the refresh rate. So for example, you have a window on this screen, which refreshes, let's say, every 30 times a second. So you'll only get that timer called that much time. So first of all, you don't need to know about the refresh rate of your device, or even more, like this screen refreshes at a different rate than this one. So we automatically know and expose it to the user. But also, it means that you will only do the calculations as you need them. So for example, we are very congested at the moment. So we're going to skip 20 frames. It shouldn't happen, but the system is loaded. So the timer will only be called once before and once after the animator, while timers may have, depends on the definition of the timer, may be queued and then called altogether afterwards, because you expect, you know, to track the time that's passed. So it's different constraints. This one is very useful for a graphical library. And we use it everywhere, obviously. And we have, you know, thread pools for thread workers. If you want to offload some things to a thread. And we can, if you're doing, like, a hacky thing, you can execute, you know, like system equivalent. And then you get the output, your monitor. And if it's still running, I did that. I don't remember what I did, actually. I used that. It's quite useful. We integrate with other main loop implementations. So, for example, you're using lib, whatever, that requires, that relies on jlib. We can integrate with jlib, so you can use that loop and just use us. And we also have networking, IPC, everything you expect. We also, back to this, we also have a tool to automatically serialize this over the network. So if you define it already to be serialized to a file automatically, you get for free the serialization over the network as well, which is very useful. And again, handles, indianess, everything you may think. So, yeah. And this is, now we're getting to the graphical part, which is, I guess, what you guys came for. So we have a canvas and scene library. So a scene graph, sorry. So a scene graph is something that comes from the gaming industry. So essentially what it does, we have a graph, we have a tree of all of the objects in the system, and we only go where it's relevant and only work on those that are in the area of interest, not clipped outside, not positioned outside. So we actually, we ignore most of the scene if it's not relevant. So you can have a list, you can have a lot of the list outside of the, I mean, we optimize that as well, but let's assume we have a lot of the list outside of the viewport, those are not even treated. Those are just ignored. So it makes everything much faster. And because we have all of the information, so the opposite of that would be direct rendering, so you just, you call every object and you just say, render now and then it checks on itself. So because we do that, because we have all of the tree and all of the information, we can ignore a lot of things and we can only render when we're ready. So we don't have any flickering, we don't have any, oh, this is just like rendered, not rendered, why? So everything just looks good. And also we don't have any tiering, we do double or triple buffering, whatever you prefer. What else do we do? Oh yeah, we support OpenGL and we have Vulkan support on the way. I'm actually not sure if Vulkan is ready. I think it's not ready yet, but if it's ready internally by, I don't know, I think maybe in Samsung, I have no idea, but anyhow it's coming. And it really saves a lot because we have a lot of, you know, hacks to leverage OpenGL essentially using what Vulkan provides. It's really, it's going to be really beneficial for us. And we also abstract away the engines. So if I would develop an app for the phone, I would develop it on my computer, run it as normally, I could resize the window or whatever I like because everything is scalable. And then when I'm ready I'm just going to tell it, okay, run on the phone that actually uses Wayland or, for example, we have a few apps and then when we switch to Wayland, everything just works, including copy-paste. Or another example, which is great, is when you're stuck without X, you can just run the terminal emulator in the frame buffer with mouse support, copy and paste, everything you may want, everything just works because the applications themselves are not aware of the engine behind. So we also have the theme and layout library, which now that we have the basic canvas and scene graph, this is like really the heavy lifting. So what we do, we don't... So you want to create an app. We don't set the color of the button. We don't do those kind of things. What you do instead, you create a small theme file, which is a very easy language. Yeah, it's another language to learn, but you also have graphical tools to let you edit it. And then in that file you can apply on buttons. So I mean I'll show, actually let's jump there. So for example here, you have these buttons are the same as all of these buttons everywhere. And the scholar is the same as this scholar. It's the same widget, exactly the same everything, but just whoever wrote that application just changed the theme on those. And everything just works. You can have round buttons. You can have whatever you want. And you see it looks like a completely different application because you can literally do whatever you want. So obviously we use it everywhere. And the nice thing about it is that you separate your design from your code. So normally let's say you have an error message, like an error situation. So normally you'd write some code that says, okay, set this text to red because we're in errors. And this is not very useful if you plan on migrating your application to a one bit screen afterwards. That is only black and white because red doesn't mean anything. So what we do, we just send to the theme. We send it a message saying we are now in alert mode. And you can change it to whatever you want. You can apply the color or you can have like a dancing exclamation marks. You can do whatever you want, animations. So in the example here, for example, when they play music, oh it's not that screen, but when they play music they have like a rotating disk of only just a play button and the pause button. Yeah, so essentially designers do design, developers do code. It makes the separation very easy. And yeah, oh, as I said, it's scalable, resizable, everything just stretches and compresses, condenses. So okay, so what, so now you want to write an application and I mentioned the widgets so you actually need to use them. So we have a lot of widgets, actually a bit too many. We are in the process of removing some. I'll touch that topic a bit later. But we have a lot to choose from and all the ones you would expect. But we are a bit more mobile oriented so you wouldn't have like Excel style, you know, a lot of columns you can sort. We don't do those because it doesn't, like, we, again, we are embedded directed so we don't, we don't focus, we don't waste our time on desktop stuff. Although we have some people who do. So we support internalization, ATSPI, so screen reading. Also, actually I'm going to show a demo of that. So we support something called finger size. So everyone knows, or at least, where is this? Successful, yes. Okay, can anyone see where is the button? This is the button. Okay, so actually let's start from somewhere else. So I'll jump to a topic just because it's easier. So we also support UI mirroring. So I'm originally from Israel where we write from, we use Hebrew, which is right to left. But also, I think, a billion more people in the world use Arabic, which is also right to left. So when we detect your application is translated to the language, to one of those languages, we automatically migrate. We automatically mirror the UI. So everything just like swap spaces. This one is hard, like it's not a widget. It's hard coded to be this way, so this way it doesn't flip. But every of the widgets, all the widgets do. And it's really, I mean, I think Apple just added it now. It's very helpful, and it's been, like for Windows, in Windows it's been, I think, for Windows 95. So it's something that users expect in those countries and really helps with localization. And now I'll show the finger size back to that. So when you write, when you write application, okay, it doesn't work. My, oh, there. It's actually not... So when you write application, normally you think about scaling. You think, oh, my screen has a very high DPI. I can't see anything. I want to scale it a bit, so now everything is twice as big. But in, like, in a mobile environment, you also have a thing called finger size. So I have semi-slim finger, but some people have, like, really heavy sausages, and some people have, like, very slender. And sometimes you use a desktop profile that only has, like, one pixel. Essentially, my mouse cursor has one pixel width. So we can change the hit area to be... Did it change? I can see. Oh, because the weight is a different screen. Yeah, we do it. So you do that, and then, like, all the hit areas are now much bigger and support, like, your fat fingers, which is independent from scaling because you may have very good eyesight, but fat fingers are the other way around. So it's very useful to be able to control those separately, and that's a user controlled. So this is like a normal configuration menu. So it's a user controlled for your platform. And you can also obviously do scaling and just make everything bigger because you can't see, which actually I should have started with because it would have been easier to see from here. Yes, those two are very useful. And obviously, your eye mirror is also useful, but those two are very useful for users to control what they do. So, I mean, I got into enlightenment from the OpenMoco project. You know, if anyone remembers that, it's like it was a phone back in the days. I thought it was very cool. It was, like, a pre-iPhone, and I got one. And I really, like, I was enjoying it, but the problem is all of my friends were texting me in Hebrew, so I couldn't read it, so I had to add Hebrew support, and the graphical one, the graphical library in SHR, which is what I was using, was the EFL. Yeah, so this is how I got to it. And there, we really took, everyone was playing all the time with the scale factor and the finger size, because it was like, it wasn't a product. We just got it with the default values. Everyone tweaked it into their own needs. Okay, so now we cover everything we've had until now, but as I said, we are changing a few things. So, this is actually my baby. I worked on it for the last, I don't remember how long, a few years. So, we wanted to have an object system. I mean, we have a widget, and we do inheritance, and we always had that, and we always had some sort of inheritance, but I found it really lacking, and I saw a lot of code that was duplicated all around. Actually, let me jump two slides forward. I was like, all free. Yeah, so we had, like, a lot of L-button text set, and an entry text set, and an item text set. You have, like, a lot of duplications of the same function that was really just the same function, and it was really confusing for users to understand which function they should be calling on which widget. And so, we needed a better object system. So, we evaluated what there was. Actually, I gave a talk about why we didn't use GObject at Foster a few years ago, and GObject people agreed with me that actually the cons that we mentioned are relevant. So, it's not just a random case of not invented here. This actually has some valid points, valid reasons. So, and also, we had a few object systems of our own inside. So, we merged them. And now, we have just one object system to hold them all. And we have, we use IDs instead of pointers. So, as part of my work at Samsung, I've been getting, I've gotten a lot of backtraces over the years. And all of them were, I mean, we have a main loop. So, the main loop dispatches all the events. So, we have the main loop, and then we have, like, an event dispatch and then user code. And then, like, that's the backtrace. So, obviously, the FL was in every backtrace. So, I got a million, like, I would get a lot of backtraces today for every user error. And we started to realize that people may be, I don't know, don't under, just seg-fold more. Like, let's not put it in nice words. So, a lot of people write a lot of codes that seg-folds. And we write it as well. But it's very important to understand who's at fault if you're going to work in a platform. So, we added pointer in direction, which is the IDs, that what we do instead, we look like a pointer, but it's not really a pointer. If you try to dereference it, it's going to seg-fold. We do a lookup inside, and check it's the right type, the right thing we expect. This is how we resolve the function. So, we added a lot of safety to know this is what you're expecting it to be. And this, first of all, we found a lot of bugs in the window manager, and that was calling the wrong functions and the wrong objects. But also, this started saving us. Like, now I get many more, many less backtraces. So, that's good. So, we do, it's an object system. So, we do classes, we do mix-ins, we do interfaces, like, as you would expect. But we also do something called composite objects, which maybe is available elsewhere. I don't remember seeing it. I mean, maybe actually in Objective-C, you have it to an extent. So, think about a car. Like, let's go to, again, Computer Science 101. So, a car is, let's say, inherits from a moving object, or whatever. So, a moving object moves, but it doesn't necessarily have wheels or anything. So, a car will add that to the class. But the car doesn't, it's not a car that inherits from moving object and inherits from wheels and inherits from chairs. It actually composites all of those. So, it says, I'm a car, I'm a moving object. But also, inside of me, I have a few things. Not them, but I have them. So, how it translates to code. In the code, you call a function, and we automatically know to divert it to the wheel. So, you can say, car, what is the color of your wheel? And it will return the value. And also, you can say, wheel, what is the color of your wheel? And it will return the value. So, that was really beneficial, because we saved, we had a lot of widgets that were composed of a lot of other widgets. So, we, again, reduced, slashed a lot of code, a lot of duplication. I love this one. We have a lot of safety and sanity checks all around. We do ref counting, weak reference counting, named xref, so named reference counting. We do parents and children relationships. So, we have a lot of mechanisms to ease the life cycle of everything. So, for example, another example we have, let's assume we have a bouncing ball, like a bouncing ball animation. So, back in the days, we would write, like we would create an image, and then we'll attach an animator that would just tick and we'll change the image, let's say, every frame. But the problem that users and ourselves often encountered is that we would delete the image, but we would still have the timer alive because we would forget to remove it. So, we'd have a sec fault because it's trying to access the image that no longer exists. But now, you just make the timer, or the animator, a child of the image, and it will automatically be deleted. So, again, a lot of those things that are not really significant, but really help to create safe code. I mean, C is a battlefield. You have to always make sure to keep it okay. This is a new thing. I added it last week. It's a nice trick. I'm actually going to write a blog post about that. So, what we do, we compile all of the object system twice, the library twice, once normally, and once with another define that adds a lot of overhead, but a lot of safety checks as well. So, it wouldn't be feasible to include it in the normal running thing. And this is so deep inside of our graphical toolkit that actually adding an if in some of those functions really introduced significant overhead. So, think you have your ref. Every time you ref an object, like adding an if to a plus-plus really doubles the size of the function, and it's, again, called all the time. So, it really slows everything down. So, our solution was to use linker tricks, essentially LD preload, to load a different library that adds a lot of debug information and tracking. We create everything on runtime. So, if you have bindings, you can just manipulate whatever you want. And we also thread safe, as you would expect. So, now we created this object system. It was great, and everyone was happy, or some people were happy. But the problem with that is now you have this overhead to define it. So, we decided, which is something I'm usually against, but we decided in this case to create an API definition language, essentially a domain-specific language for our APIs. And once you explore it a bit, you see it's actually quite a good idea, because first of all, we validate all of the API and the documentation beforehand. So, we have documentation that references other APIs. We know in advance that it is okay and will be okay. And you say, oh, but Doxygen does it as well, whatever. But the problem with Doxygen doing that, first of all, that it's not part of the normal built path. So, people do not build Doxygen all the time. And second of all, with Doxygen, you don't have the highlighting, you don't have... Like, it's not core. So, it doesn't have the same knowledge as we have about what's going on, dependencies, what is crossed, what is used, where this library can depend on another library and define systems. We found this, again, this sounds a lot like not inventing a syndrome, but trust me, it actually really helps us. And also, we needed more things. So, we decided we're not going to write bindings anymore. Like, we've had enough. It's hard to do them. It's really hard to do everything and just keep track and update changes, and then you miss a feature here. You need a lot of army of people to update them. So, we decided to do it automatically. But for that, we needed some extra information, like ownership, who owns this object? I returned a string. Are you supposed to free it? Am I supposed to free it? So, this domain specific language added a lot of annotation to all of our functions. And as I said, we didn't want the boilerplate, so we generate the C implementation and the headers automatically. So, all of... When you build EFL, it just runs, generates everything, and then compiles. We generate bindings. So, we don't have any fully working bindings now because we haven't annotated all of our API. We've had years of APIs that we need to annotate, but we have generators for Python kind of, C++ and Lua, that are there, but just leak a bit because we don't have all of this. And we also generate API documentation, which I'll get to in a second. So, this is how the language looks like. Again, it's... Sorry. It's a bit simpler than the C equivalent because we had to limit ourselves to what is easily bindable. So, for example, we don't have function callbacks. We assume you use our callback mechanism or use one of the other mechanisms we do. We allow you in order to add your own specific callbacks. So, we have a basic event system, but we don't allow you to add other callbacks. So, we do import extra types. So, Ina types is the general purpose library. So, you have lists and all of that. Structure, you just name is a string. This is how the, you know, how the... How do you call it? How the documentation looks like. True is like a built-in symbol. So, you look at monospace whenever you generate it. This is a reference to an EFL class. So, we have... Oh, this is a class. Inherits, inherits, mixin. But we also have properties. So, in C, it will look like... It will generate two functions. So, parent set and parent get. But in Python, for example, we can use the native properties of the function. So, this also means that our API now looks better in other languages, which is very useful. Yeah, you can see some ownership, and you can see this one is allowed to be now... Yeah, this is how it looks like. So, we got... So, we organized a few namespaces, and the inheritance tree in general, we renamed. So, we had, as we saw, Ina, It, Eva... Like, a lot of random names that don't mean... Do not mean anything to anyone. So, had I given this talk like four years ago, I would have shown you a big slide of the hierarchy of all of our libraries. So, this is it, and I'll teach you ten different names. Now, we don't do that anymore. We just have EFL.UI, EFL.... Oh, God, text. EFL, all of those, and you just... In a very organized and clean namespace. Almost everything is an object. So, we have, as I said, timers. We have... Oh, network connections. We have a lot of things. Promises we have nowadays that are objects. And as I showed you earlier, we just have one function to use everywhere. And we also took the opportunity because we're rewriting all of the API to fix some design mistakes. And now I'll jump, like, way to the beginning. So, when I promise you we have stable ABI and API, this promise still holds. We'll still expose all of the... We'll still expose all of the old functions that behave the same way. So, things haven't changed. So, if you wrote code a year ago, it will still work. Just like an important thing to note. And we also have the documentation system, as I mentioned. So, we thought documentation is hard because developers don't want to do it. And non-developers usually don't want to dive deep into Git and start finding the functions in the headers and, you know, add some information because all they wanted to write was a simple app. They don't really know, you know, writing big, like, I don't know how many lines of code. See libraries. So, we decided to do a wiki that... And we used local wiki so it skipped back. So, we have a wiki which is partially read-only, partially read-write. So, we generate all the read-only parts from the EO files, which are the domain-specific language. So, you'll have all the documentation shown there and all the references automatically there. And then you have a section you can edit that adds more examples or more, I don't know, examples in C, examples in JavaScript, example in Python. So, everything is generated by a certain convention that then we know our templates and plug-ins in local wiki and know how to interpret it so you can have it... For example, you can only see Python examples. So, this one is a very good one. If we have time in the end, I'll show an example of this one. Okay. So, now, like, this is what we... This is what we do. This is who we are. And we also have development tools to help you develop. So, we have Clousseau, which is a UI inspector. So, it makes it very easy to, like, inspect all of the UI elements that you have. You go and you just, you know, you look and this button is this size and this color. So, it's really useful for debugging. It works with GDB. You can do it remotely. You set it... You can either set an environment variable or configuration. So, this one is like a lifesaver. And also, you can save it everything and load it later. So, when I get bug reports nowadays, I just ask for a dump of this and so I can look it up afterwards. Yeah, and, you know, pick some inspection, everything you'd expect. And we also have an ID. It's still under development, but it does, you make a Clang integration. So, it's a nice environment if you're into that. I mean, I use Vim, so I don't really use it, but it's nice. People like it. Just worth a mention. And we also have, like, you know, a GUI builder, Edge, which is the theme library editor. We have a Pixel Perfect test suite to make sure your app hasn't changed what you didn't expect it to, or our library hasn't changed what we didn't expect it to. Yeah, I'm just like rushing a bit because time is running out because we started a bit late. So, EFL can fit into eight megabytes or maybe bytes on disk with static compilation, minimal dependencies. If you want to get out, you've got to get rid of the GUI libraries as well for some reason, because you want to render on your own into the canvas. You can do that, and then it's only one megabyte, but think about it. You will need some resources. You will probably get, you know, back into fatness area afterwards. So it doesn't really help that much. We do software rendering. We do GPU rendering. We use the GPU to its fullest extent. If the driver supports it, you'll do partial updates. We'll do whatever. We're very, I mean, not me, but a lot of us are very, like, graphic geeks. So we use, like, a lot of everything, all the extensions, all the... Love graphics, essentially. So I would have given you, like, how much RAM we use, but it really depends on the screen size, because, again, we are graphic libraries. If you have this big of an image, it differs from this big. But this is an example that a colleague of mine ran Enlightment to align EFL applications on Arch Linux in a desktop profile, so, like, a fully bloated desktop. And this was the system. Like, so 300 MHz, 48 Mb of RAM, the system, not actual usage. And the display, and he says, it runs well. Like, this is, like, the most hearsay thing in the world, but still, it actually, it works in those kind of settings. So I'm going to rush for this, but I'm just going to show you. So we run a lot of things. So back in, like, we run on a Samsung Watch, and the newer Samsung Watch, which actually has a circular screen. I mean, those are high-powered devices, but we do the open moco, as I said, but also a new Samsung Z2. We run on fridges. This one is cool, actually, because we did rotation in software. Whoever did that, so that was actually, that's more computation-intensive, and it still ran, okay, on this 400 MHz device. Massive fridge, and you know, more things like cameras, TVs, and, like, this is a GPS alert thing for your car, so if you're speeding, it will pop an alert, like this thing. And a printer, yeah, run on a printer, whatever. And also, as I mentioned, the, like, the voltage meter, I just don't have a picture of that one. And, you know, we run, we have a lot of different applications for Tizen that were written using DFL. So actually, there are a lot of use cases that are covered. So if you want to write an application, you probably, someone wrote a similar UI or similar, everything. So you're going to be sure it's going to be okay. We have, like, a photo thing. And we have this. This is, like, what I've been waiting for. So I don't know, does anyone here know what terminology? Show of hands. One, two, three, four, five. Okay, six, seven. Yeah, so this is, like, a crazy terminal emulator that was created because we can, which is usually a bad reason to create things, but this one happened to be a good accident. And so it runs, of course, an X-Wailer and a frame buffer, everything you may want. And although it's crazy, it actually has some cool features. So first of all, everything can be themed. Let me just... Everything can be themed. So everything you would expect, thanks to our theming library, can happen. Let me just... Oops. There we go. So let's do this one. Okay, so I just LS in the terminal, and I have thumbnails, which is very useful for someone like me who actually works with images all the time. And then, oh, there's a link. This is, like, the... Sorry, this is a thumbnail. I just click on it, and it, you know, shows me, like, a pop-up of the thing. And it also works with a lot of other situations. So wait, before that, actually, I can... Let's see if I can do it without... Front-size a bit. Front-size, yeah, I can do that if I can see what I'm doing. Oh, yeah, it's still on the... with a massive scaling factor we set earlier, so I don't know if... I don't know if I can... Ah, because I'm using a fixed-size font, so, like, I can't resize it. I need to choose another one. Let's hope this one is good. Okay, it's gonna mean it looks super ugly, but let's... Oh, God, yeah. Okay, that was a mistake. Actually, let me just do this. I mean, okay, it doesn't really... We don't really need the font, to be honest, because we are not... Oh, God, I just ruined everything. Yeah, now, because everything is so big here. Okay, so let's assume, for whatever reason, I want to set an image as my terminal background, and why doesn't it work? Okay, I don't know what... Oh, yeah, I copied the wrong thing. So, I can set... Like, this is my background. Yeah, it's not very useful, but I can also do this, which is more useful. I can. So, I can also do ls, not just on images, but also... CCD instead of CD. Thank you. Yeah, no? Yeah, okay. You see, so I can also do it for videos. It's hard to see, but let's click on one, for example, and you'll have video rendering inside your terminal, which also works remotely. I mean, you're laughing like, ah, we need that. But actually, I use... How do you call it? WeChat. So, this is... I use IRC in my terminal, and then someone paste a link every now and then to an image. I just inline view it. I don't need to leave my terminal. Yeah, so this is like a full-blown thing, but you see, like, you know, like popping out those things... Wait, there. Now it's better. Did I see it? Yeah, so I can also just, like, do a cat. So, you do, like, all the videos in Maya, I think, it's like a video from Foslem. Like, it's all running in parallel. Yeah, so, I mean, yeah. And when you scroll it, it stops playback, as you can see, no more sound, as you would expect from a terminal that plays videos. Yeah, and that's that. I mean, that's a cool one. I think, actually, I recommend you use it. Okay, so let's just wrap it up real quick. So, this is where you can find more information. Again, the slides are up online, so you can just look there, because we're running out of time. So, do you have any questions? Like, we have time for one, I think. Yeah. So, yes and no. So, the reason is, we have the domain-specific language, and that one is not EFL-based. So, you can use, if you generate, if you use the same language to describe your project, yes, you can use it, definitely, and you can also use it to create your own boilerplate. But you have to write your own generator. So, we have a general-purpose library that passes this format, but we have generators that generate EFL-specific information. Okay? Yeah. Two questions. Okay. How do you use the system-making use to process a file? I have no idea. But, I mean, it's, you know... What kind of systems? Yeah, yeah, but the thing is, I work on that part of it. You know, I don't... But we use it in Tizen, and we use, I think, OBS, like the open-source build system. I don't know. But when I used to work it on... When I used to work on OpenMoco, we used to use OpenEmbedded, which is now Yocto. So, I mean, that would still work. But I don't, you know, I don't... I don't live in the front line of that aspect, so I can't really give you, like, a good educated answer. I can give you, like, a five-year-old answer. So, ask someone else. Oh. IRC or whatever. Like, we've been... Yeah? There are some layers. Pardon? There are some layers. For Yocto? Yeah. Yeah, he works in Tizen, so... So, yes and no. I mean, no, but... But we're open to that. Like, so we... I actually wanted to experiment with Rust the other day, and I was going to write one for Rust, but then I got, like, okay, I actually have better things to do, like, finish the slides. But, yeah, but other than that, we tried... We know... We have a lot of language references. We have, like, some people do... I don't know how to pronounce that, but, oh, come on. Yeah, we have some functional programming. We have C. We have C++. We have Python. So, we have, like... We had an assortment of languages that we knew we could work with. So, we assume other things would work as well. But, no, we don't... We don't... And especially, you know, Vala is very geo-objective. So, I don't know how many things would actually translate nicely. Yeah, because Vala... Vala started back when, when the open mocha days were, like... So, we started... Actually, I started doing Vala, some Vala work back then. But, I don't recall... I don't remember anything. I don't know how to say... I don't know anything about it nowadays. Okay, I think we need to wrap it up. Yeah, or... We don't have any more time for more questions, anyway. So, cool. Thank you very much for coming. Yeah. Yeah.