Google Summer of Code 2020 @ Kodi Reflection

Alex Ionkov
6 min readSep 2, 2020

Over the past three months, I designed a new web interface for Kodi in Elm backed by Google’s Summer of Code (GSoC) internship program. This was the most extensive project I have worked on to date, as I wrote a 10k LOC Elm SPA, wrote JSON-RPC decoders and partial wrappers, and designed UI using elm-UI. GSoC entailed becoming a part of the Kodi community, as well as achieving significant progress on three deliverables in which I outlined in my proposal/application for the program.

Why Kodi?

My background and passion for designing web interfaces are what initially attracted me to work for Kodi. While I was not very familiar with Kodi prior to this summer, I had been briefly exposed to web media interfaces when I was in middle school. At the time I had installed Raspbmc (XBMC) on my Raspberry Pi 1 after Raspbian and developed a small library of songs and played around with Addons. While I thoroughly looked at several other organizations, I was enticed by Kodi as their organization would let me pursue my interest in web GUI design and development. Once I had my mind set on Kodi, I wrote a forum post asking about more details and offered some UI ideas. My project proposal was to write a new maintainable web interface to replace chorus2, a Coffeescript project.

Community Bonding

Over a substantial number of forum posts, I became closer to my mentor, Kolja Lampe (a.k.a Razzee) as we decided on a programming language and framework. Razzee suggested several functional languages including Elm or Svelte. After weighing in the options, I decided on Elm, a fairly young functional language written by Evan Czaplick.

This was my first project using a functional language. Accordingly, learning the structure and syntax was a very challenging yet exciting experience. Programming in Elm requires that you have a central Model which is an accessible immutable data structure and every Message creates a modified copy of the Model and replaces the central one. This concept of modifying data flow with custom types was foreign to me and took me quite some time to learn even the basics. In my opinion, learning technologies for projects is the most fun way to learn and made the entire process feel very rewarding as I could look back at my growth.

Phase 1 (June 1 — July 3)

To start the project, I had to decide on a way to communicate with Kodi. Kodi has JSON-RPC and Websocket support. JSON-RPC can be used to test commands and small scripts, but to have real-time communication with Kodi, a web app needs to use WebSockets. Fortunately for me, there was an example demo of connecting to WebSockets with Elm in which I had based my project (elm-kodirpc). The purpose was to build a parser and a wrapper for Kodi JSON messages in Elm. I had to start with examples; never start from nothing.

The first thing I realized after making a rough user interface with elm-ui and ellie, was that I needed to be able to parse the JSON-RPC responses from Kodi for communication. In Elm, decoders can be confusing if you are not familiar with them, but it turns out they are actually pretty simple (A lot of things are simple in Elm once you know how to do them :)). Using the Json.Decode.Pipeline package you can build decoders with the pipe symbol ( “ |> ”) like so:

type alias User ={ id : Int, name : String, email : String}userDecoder : Decoder UseruserDecoder =Decode.succeed User|> required “id” int|> required “name” string|> required “email” string

“string” is a provided string decoder which means you can write your own custom type decoders and plug them in very easily. I considered this part of the project the “backend”, this was essentially writing a JSON parser for Kodi responses.

At the same time, I needed a way to send messages to Kodi. I found wrappers for building and sending JSON messages to Kodi in Python and other languages, so I naively decided that I would just write a wrapper exactly like them (such a simple task :) ). In Elm and other functional languages, you have to know exactly what kind of data you are processing. If you don’t, you can use Maybe to account for null or empty possibilities. Dealing with Maybes, as I eventually found, is a very daunting task as you have to keep wrapping and unwrapping the fields. It was at this point where I mostly abandoned my efforts with elm-kodirpc and started just using JSON strings to send messages. In reality, there are not that many messages that you need to send to Kodi for a web interface so you don’t need a wrapper, but it sure makes it nicer.

Phase 2 (June 3 — July 31)

After I came to the bleak realization of all the time I wasted, I started focusing on the decoders and the GUI.

First basic UI made with elm-ui and ellie

The user interface we were building in Elm used a package called elm-ui which allows you to create elements that are easy to use in Elm and also convert to HTML. To build a single page application in Elm there are a lot of things that you have to consider. You have to think about routing and dealing with url changes etc. — all things outside the scope of this project — so I chose a framework called Elm-spa which took care of routing and page generation for me. Elm-spa has a really nice Slack channel and the creator, Ryan, who hangs around there a lot, is a very friendly and helpful person to ask. I definitely asked a lot of foolish questions in that channel.

Phase 3 (July 31 — August 31)

Halfway through August I contracted COVID and my productivity was pretty low. Despite feeling tired all the time, Razzee and I managed to make great progress and a lot of the UI implementation happened in August. I also worked on using localStorage to store playlists locally. LocalStorage lets you store data in the DOM across browser sessions.

The resulting project (elm-chorus) has a lot of chorus2’s major functionality and interface implemented. Many of the hard problems (layout problems and others) in this project were solved by Razzee, who has been very helpful.

This summer was a huge learning experience for me. We managed to build a partial copy of chorus2 in Elm which is pretty cool to me; it’s my first project with over 10k lines of code. It being such a large project helped me learn how to manage a bigger codebase like modularizing parts. I learned Elm, my first functional language! It is a different way of thinking about programming which I found very challenging at first but ultimately, really intriguing and surprisingly easier than I anticipated. I think this experience will help me learn TypeScript and other languages faster. I am looking forward to continuing elm-chorus, and am hopeful this experience will help me apply what I have learned to new projects with others in the future!

PS: Many thanks to Razzee for answering many questions and helping me learn how to use Elm, ports, elm-ui, and elm-spa.

Link to the elm-chorus Github repo.

Music page of elm-chorus

--

--

Alex Ionkov

Computer Science student at UW Madison. I like moving fast and thinking slowly.