Wednesday, December 20, 2017

3.0 Work in Progress 13: Cuesheet improvements

Most of the work I've done since the last post has been behind the scenes so there is not too much to show.  I rewrote the audioengine management piece (what handles the interaction with gonemads audioengine, android media player, and chromecast), rewrote the crossfade code, and cuesheet handling.

Cuesheets are something that the majority of gmmp's user base probably does not use, but they are a nice feature.  For those who do not know, a cue sheet allows you to listen to a single large audio file as if it was split up into tracks for each song.  GMMP has always had decent support for CUE files (they would appear as individual tracks in the library views), however in the folder browser they would just appear as a .cue file and the single mp3 / audio file. 

In 3.0, the folder browser will actually extract and list the individual tracks in a CUE instead of the single file.

Below is what the actual folder on disk looks like.  This example is a single cuesheet with 5 separate hour long mp3 files (its a electronic/trance mix i believe).

Folder view from solid explorer

This is how it will now appear in GMMP 3.0

Cuesheets can also be embedded into the tags of files.  GMMP supports that as well

Next up will be the new equalizer / effects UI.  I will most likely also rewrite a lot of the underlying DSP/EQ code as well. 

Friday, December 1, 2017

3.0 Work in Progress 12: File Browser UI

Next up on the new UI list is the file/folder browser.  I also rewrote the file/playlist handling on the backend to be much more streamlined.  A lot used to go on when playing folders and i've greatly simplified that.  As always, the file browser will show anything on the file system and does not care if its in the database or not.  This is great for navigating, but caused a lot of issues when a user went to play a file or folder.  I am sure some were familiar with the issue where songs would "disappear" from the queue after reloading GMMP.  This was because the user played a file that was not scanned into the database.  GMMP would play the file fine in the queue, but when the queue was persisted to the database those files were lost.  In 2.x GMMP would try its best to get everything scanned in by running silent scans of folders as you navigate into them.  While being pretty inefficient, it worked for the most part.  The big issue happened when a user would select a folder to be played and that folders contents were not scanned it.  GMMP did a bunch of stuff to account for this, but in the end it was very hacky/ugly and really bloated the codebase.

This time around for 3.0 I came up with a much better approach.  The new UI / data backend has some nice capabilities like auto updating when its backing data in the database changes.  Now when a file is played, GMMP will look to see if its in the db, if not it creates a placeholder on the spot.  The placeholder just contains the filename and a track id which is all that is needed for putting a song in the queue.  If any placeholders were created, gmmp will then run a scan to populate all the placeholders with the information from the tags.  Any UI that was displaying the placeholder will auto refresh and show the tag metadata.  So now there should never be a case where files are lost from the queue on restart.

New UI (I switched up the theme colors just to add some variety to the screenshots)

At the top is the QuickNav which is scrollable horizontally and each folder is clickable to instantly jump back up a few folders (the video below will show this).  Like every other list item, the metadata shown is customizable.  In this screenshot below the first item is a playlist which is just displaying its filename and the items below that are showing the song name and duration.

I plan on adding the ability to highlight the currently playing track (i also think i can add that ability to the library views. I know this is requested often).

Sunday, November 19, 2017

3.0 Work in Progress 11: Bookmarks, Chrome OS, and Permissions

I recently picked up one of the new Google Pixelbooks and I will say it a pretty awesome development device.  It runs Chrome OS, Android, and Linux all at the same time and has pretty good specs (i5 cpu, 8 gb ram, 128 gb ssd) for running Android Studio.  I am able to code and deploy GMMP right on the same device which makes development really convenient when not at home.   Android apps also run in their own window which can be resized which makes UI testing on different size screens super easy.

Ignore the artifacts around the window containing GMMP.  It is a side effect of taking a screenshot i guess (it appears fine on the device)
In order to support the free form resizing of the app window, I updated the target SDK level to 27 (android 8.1).  GMMP 2.x was still on 21 (android 5.0).  The target SDK update should see some performance improvement in newer devices (although i do not know by how much).  I also added support for the android permission system they added back in 5.1.  GMMP should only ask for storage permission and possibly phone state permission (if you want to use the auto resume after a phone call finishes feature).

Anyway, the main focus of WIP 11 is bookmarks.  In the process of refactoring / rewriting the MusicService, I rewrote the Bookmarker and added a UI to show existing bookmarks.  All of the previous work I spent on creating common, reusable UI components is really paying off.  Adding a functional bookmark list UI only took roughly 15 to 30 minutes.  Similarly the Artist and Genre details UIs I showed in WIP 10 took about the same amount of time.  Since its so quick to add these UIs, I can see myself adding a bunch of optional views for some other fields like year or composer (and making 2 separate UIs for artist / album artist if the user wants to have both easily accessible)

The bookmark list will show all the currently bookmarked tracks and let you play them directly from the list (or delete them).  Like every other view i've shown in 3.0 so far, the metadata will be customizable.  For this post I just had the list items show song name and bookmarked time.  For the video below I set it up to just auto bookmark everything, but the previous bookmark settings will still be there in 3.0 (auto bookmark based of song length, m4b extension, or by folder). The video will show the song auto bookmarking when changing tracks, and then resuming at the same position when returning to the song.  It also shows the manual bookmarking and unbookmarking of the currently playing song.

My focus next will be creating a folder UI.  The folder UI is a bit more complex than the other UIs (besides maybe now playing) so I imagine its going to take awhile

Sunday, November 5, 2017

3.0 Work in Progress 10: Multiple Artists and Genres Per Track

In the last few weeks I've been mostly doing backend work so there arent too many UI changes to show off.  The music service refactor / rewrite has caused me to rewrite a few of the other backend systems (and there will probably be a bunch more that need it to).  Since I was already making so many changes to the data access layer, I decided now would be the best time to basically clean up the whole data model and make the necessary changes to support some of the highest requested features like supporting multiple artists and multiple genres.  These changes led me to rewrite the scanner entirely (I had to do it anyway due to the data access layer changes).  Now the scanner will recognize artists and genres that are delimited by a specific character (";" by default) and set them up in the database accordingly.  Since fields with the ";" in it are a bit ugly.. i do plan on adding some functionality to replace that with "and" or "&" or really whatever phrase you want when displaying the song in now playing / notifications / etc.  That hasnt been implemented yet so these screenshots will show the delimiter. 

In order to show this in app, I quickly coded up a artist and genre details UI.  The plan is to show some sort of artist / genre image at the top similar to the album details view.  Right now its just a solid color background.

Properties of the test file with multiple artists and genres
Song in app

As you might have guessed, there wont be an alpha version ready to test anytime this year.  My first child is expected to be born in a few weeks so it is unclear how much dev time I will be getting in the near future, but I will try my best to continue the WIP posts and get something testable in the early 2018 time frame (hopefully)

Saturday, October 14, 2017

3.0 Work in Progress 9: Shuffle and Notifications

The last update I showed off the new queue ui which did involve a complete rewrite of the underlying queue backend code.  Due to that and switching to the new data model (Room-based), I ended up taking the plunge and rewriting the MusicService.  It seemed like a waste to try to hack it up to use all the new stuff I added when I eventually planned on rewriting it anyway.  Due to that I dont have too much to show UI wise, but I did make some queue improvements and redid how shuffle works.

One of the largest complaints I've gotten over the years was the inability to skip back/forward while shuffled and get a consistent track order.  Once you skipped back, the next track would be chosen at random.  My response was always that I understood the frustration but without rewriting shuffle / music service entirely there was not much i could do.  Since I am rewriting the music service and queue, this seemed like the perfect opportunity to fix this issue.

In the video below, it shows off the new shuffle queue.  It essentially works like the "randomize" option in the queue.  Turning it on will put your current playing song at position 1 and shuffle the order of the rest.  Pressing next track will simply just go to the next track in the queue.  This allows you to go back and forth and maintain the same order.  This also greatly simplifies the code on the backend.  Next track doesnt care if its in shuffle or not.. it just goes to the next track listed in the queue.  When shuffle is turned off it will return to the previous order.  Any new tracks added while in shuffle will just be placed at the end when shuffle is turned off.  Note: For this video and testing i added a shuffle button to the min player at the bottom.  This was just so i could keep the queue up and change the mode back and forth.

Notifications were managed by the MusicService, so I gave them a rewrite as well.  Google has added a lot API since I originally created these notifications, so this time around I will just leverage what they provide instead of doing a custom view for it.  These newer notification apis will also allow album art to play on your lockscreen on devices that it didnt work before (most phones would already show the album art on the lockscreen but a select few would not). 

Plans for the notifications will be 5 customizable button slots (most likely just the common actions like next / prev / play/pause / exit / toggle shuffle) and 2 (maybe 3?) metadata lines that are customizable like the other metadata views I've shown in previous updates.  The images below just show off the standard next play/pause and prev buttons.

Lineage OS 7.1.2
Lineage OS 7.1.2
Galaxy S5 running 6.0.1

Friday, September 22, 2017

3.0 Work in Progress 8: Queue

Its been awhile since I've posted a new update but I spent a few weeks working on 2.2.4/2.2.5 and now I am back working on 3.0.  This next update focuses on the queue.  Its not finished but it is working enough that I can show it off.

The queue involved a bunch more work than the previous views since I had to rewrite the actual backing queue data structure.  Previously the Queue class would retain its own copy of the tracks and it was in charge of persisting all changes into the database.  This time around I made it much simpler by just keeping everything straight in the database, so the queue and db no longer have to stay in sync.

The queue features drag and drop like the previous version of gmmp, however it is done a bit differently (at least for now pending feedback).  Instead of having the "handle" on the left on each list item that you press to start dragging, dragging is now started via a long press.  The reasoning behind the behavior.. honestly.. is the drag and drop helper class that google provides works this way .  I didnt see any reason to reinvent the wheel.  Also deleting can be done via swiping left.

Due to the swipe left to delete, I have chosen to not make the Queue available to be placed as one of the library tabs.  However, the queue will be accessible straight from now playing via the FAB (this is shown in the video), and via the side navigation drawer.  I originally had the queue in as a tab and it was too unreliable trying to delete.  Half the time it would just scroll over to the next tab.

Just like all the other views, the metadata displayed in the queue will be customizable.  I also improved the metadata views quite a bit by adding the ability to define how much space each "slot/alignment" takes up (see WIP 1 for details).   This allows for something like the image above.  The song title and artist will take up 80% of the view and the track duration only takes up 20%.  Below is the code that represents the queue list item:

 var metadataLinesModel = MetadataLinesModel(GMThemeEngine.getInstance(context).currentTheme).apply {  
       addMetadataLine(arrayOf("<weight=0.8><align=left><typeface=sans-serif><size=16>%ps%. %tr%", "<weight=0.2><align=right><typeface=sans-serif><size=16>%du%" ))  

Here is the video of the queue in action

Wednesday, August 30, 2017


I was finally able to work out some of the sdcard write issues.  I could only reproduce issues when creating playlists, so hopefully that was the only problem.  I also tested with android O (the emulator) and didnt experience any issues, so GMMP should be good to go for 8.0

2.2.4 (08/29/2017):
-Updated google services to 11.0.4
-Updated support libraries to 26.0.0
-Updated compile sdk to Android O
-Fixed bug where keyboard would not show when using a gesture to jump to search
-Play next/prev album now orders by album name instead of by artist (use next/prev album by artist for other behavior)
-Reset anything set to next/prev album to next/prev album by artist
-Notification will now properly update state when queue completes with on queue completion set to default or stop
-Audio focus is now only abandoned when the music service is destroyed
-Fixed audioengine startup race condition deadlock
-Fixed creating new files on sdcard (playlists / downloaded album art)
-Fixed issue where some m4a files would play at the incorrect sample rate

2.2.3 (05/02/2017):
-Update google services to 10.2.4
-Fixed some audioengine crashes
-Fixed other various crashes and bugs

Monday, August 14, 2017

3.0 Work in Progress 7: Fast Scroll & Gestures

The last 2 weeks I added in fast scroll (scroll through long lists fast by dragging down the bar on the right with the letter / number indicator to show where you are in the list) and gestures on now playing and the mini player.

The first up is fast scroll.  This rendition of fast scroll SHOULD be a bit more consistent than the old one in 2.0.  There was a random bug that was very difficult to reproduce that would cause the letters to not match what was showing on the screen.  The fast scroll code is much simpler this time around so i dont expect that bug to be an issue.  The video is a big laggy and the fast scroll in general is not as smooth as i'd like it to be, but that will be worked on once 3.0 gets to beta.

The second feature is the addition of gestures.  All the previous gestures have returned (swipe left right up down / tap / double tap / long press) plus I added in a few more.  New gestures are 2 finger tap/double tap/long press, and a 2 finger pan.  The pan is considered a "continuous" gesture, so there will only be a few actions that you can bind to it.  The video shows it bound to adjusting the volume, but the other options would be adjusting tempo or seeking the track.  If you decide to not use the pan, you will be able to use 2 finger swipes.  Right now GMMP is using the stock version of the gesture library and it works fairly decent for the most part.   If users find some gestures hard to use I will try to tweak the library to improve that.

My next 3.0 post on here will most likely not be for another 3-4 weeks since I have a vacation coming up and I plan on doing a 2.x patch for android O plus some other bug reports i've gotten over the past few months.

Saturday, July 29, 2017

3.0 Work in Progress 6: Mini Player

This update mainly focuses on the addition of the mini player to the bottom of the library view (and will also be on other views where it makes sense) but I did also make some improvements in the play / pause animation.

Above shows the new mini player.  Just like every other view so far, the metadata portion will be customizable and you will be able to choose how many buttons are shown.   Right now you can choose between prev track, play/pause, and next track.  I may open it up to some of the other media actions like shuffle / repeat but i havent decided on that yet.

In the WIP4 post I had shown off a little chunk of the code that added a bunch of "behaviors" to a view.  The behaviors contain all the common code for a particular behavior of a UI view.  This allows me to rewrite the same (or very similar) chunks of code for different UIs.  GMMP 1/2.x was loaded with repeated code despite my best efforts to refactor.  Anyway, since the mini player shares a lot of the same abilities as now playing, I created 2 new behaviors: PlayingInfoBehavior and MediaButtonBehavior.

So here are the behaviors for the Library view:

view?.let {
            addBehavior(LifecycleBehavior::class, StatusBarBehavior(context, it))
            addBehavior(LifecycleBehavior::class, ToolbarBehavior(this@LibraryPagerPresenter, it))
            addBehavior(LifecycleBehavior::class, PlayingInfoBehavior(context, this@LibraryPagerPresenter, it, state))
            addBehavior(LifecycleBehavior::class, MediaButtonBehavior(context, this@LibraryPagerPresenter, it, state))
            addBehavior(FragmentContainerBehavior::class, FragmentContainerBehavior(it, state))
            addBehavior(MenuBehavior::class, HasMenuBehavior())

I now set up the state of the library view for the above screenshot:

state.metadataLinesModel = MetadataLinesModel(theme).apply {

state.buttonDefinitions = mapOf( to
                                                MediaButtonDefinition(-1, R.drawable.ic_gm_pause_to_play, 0, MusicControlEvent.PLAY_PAUSE, theme.iconColorNormal),
                                                MediaButtonDefinition(0, R.drawable.ic_gm_skip_previous, 0, MusicControlEvent.PREVIOUS_TRACK, theme.iconColorNormal, View.GONE),
                                                MediaButtonDefinition(1, R.drawable.ic_gm_skip_next, 0, MusicControlEvent.NEXT_TRACK, theme.iconColorNormal, View.GONE))

The first part defines how the metadata is going to display and the second part defines the media buttons.  Tells it what icon to use, the size, the action that will happen on press, the color, and finally the visibility.  This is all "hardcoded" right now but will eventually hooked up to the preferences making it really easy to customize.

Small change in the code here to get the 3 buttons:

state.metadataLinesModel = MetadataLinesModel(theme).apply {

state.buttonDefinitions = mapOf( to
                                                MediaButtonDefinition(-1, R.drawable.ic_gm_pause_to_play, 0, MusicControlEvent.PLAY_PAUSE, theme.iconColorNormal, View.VISIBLE),
                                                MediaButtonDefinition(0, R.drawable.ic_gm_skip_previous, 0, MusicControlEvent.PREVIOUS_TRACK, theme.iconColorNormal, View.VISIBLE),
                                                MediaButtonDefinition(1, R.drawable.ic_gm_skip_next, 0, MusicControlEvent.NEXT_TRACK, theme.iconColorNormal, View.VISIBLE))

Now playing is now configured the same way:

override fun onViewAttached()

        view?.let {
            addBehavior(LifecycleBehavior::class, ToolbarBehavior(this@NowPlayingPresenter, it, false))
            addBehavior(LifecycleBehavior::class, PlayingInfoBehavior(context, this@NowPlayingPresenter, it, state))
            addBehavior(LifecycleBehavior::class, MediaButtonBehavior(context, this@NowPlayingPresenter, it, state))

    private fun createState()
        //Read state
        val theme = GMThemeEngine.getInstance(context).currentTheme
        state.metadataLinesModel = MetadataLinesModel(theme).apply {

        state.buttonDefinitions = mapOf( to MediaButtonDefinition(-1, R.drawable.ic_gm_pause_to_play_circle_outline, 0, MusicControlEvent.PLAY_PAUSE, theme.accentColor),
                               to MediaButtonDefinition(0, R.drawable.ic_gm_repeat, 0, MusicControlEvent.TOGGLE_REPEAT, theme.iconColorNormal),
                               to MediaButtonDefinition(1, R.drawable.ic_gm_skip_previous, 1, MusicControlEvent.PREVIOUS_TRACK, theme.iconColorNormal),
                               to MediaButtonDefinition(2, R.drawable.ic_gm_skip_next, 1, MusicControlEvent.NEXT_TRACK, theme.iconColorNormal),
                               to MediaButtonDefinition(3, R.drawable.ic_gm_shuffle, 0, MusicControlEvent.TOGGLE_SHUFFLE, theme.iconColorNormal))


Here is a screenshot of the play pause in now playing using the icon from the mini player.  I plan on also adding the other play icon inside the filled circle (in addition to the current play with the circle outline.

Finally here is a video of everything in action.  The animations / transitions didnt seem to record as smooth as it appears on the device, so just keep that in mind.  I do most of my testing on a galaxy s3 running 7.1.2 and an original moto x running 5.1, so if things look smooth on those old devices they should be great on the newer ones.  This video also shows a bug with the 3 dot menu getting shifted to the left a bit when coming back to the library view.  I havent really looked into that much but it'll get fixed.. no worries.

I also want to note that when 3.0 is finally released I do think I will add 2 other options for how now playing looks.  One being the colored toolbar on top, with the album art underneath it taking up all the space between the toolbar and the metadata.  The other being smaller album art centered around a blurred background generated from the album art.  Some other players use that look and i really like it.  Plus it will be a compromise for current users of the holo themes with the blurred background

Sunday, July 16, 2017

3.0 Work in Progress 5: Library view

In this update I added a library view similar to the one in the old UI.  I also added in an artist list, genre list, and track list tabs.

The big difference with this one is the toolbar will collapse when you scroll down and if you scroll up it will become visible again

Here is a video of it in action

The plan with the library view is to allow the user to choose which views to add to the library (others will end up in the side navigation view if they are not in the library), the title of those views, and their order.  Below is the chunk of code responsible for building the library, its "hardcoded" currently but will be fairly simple to hook up to the preferences.

v.setupAdapter(listOf(BaseFragmentEntry("Artists", ArtistListFragment::class)
                                  , BaseFragmentEntry("Albums", AlbumListFragment::class)
                                  , BaseFragmentEntry("Genres", GenreListFragment::class)
                                  , BaseFragmentEntry("Songs", TrackListFragment::class)))

I am sure many of you are anxious to try out the new UI, but it is still a ways off.  Some of the views are not too straight forward to code like the equalizer and the browser / folder view, so I expect they will take some time to code.  My plan is to have a working alpha by this fall.  The alpha however will not really contain much customization.  Its really easy to add customization to the code, however actually creating UIs to configure everything is going to take a long time.  Because of this, the alpha will be through a separate group in google+ that users will have to join.  I didnt want to push something so incomplete to the beta channel

Thursday, June 29, 2017

3.0 Work in Progress 4: MultiSelect, Overflow Menu, and Sort

For those who havent noticed, I am trying to do post progess updates every 2 weeks.  This iteration doesnt have too much to actually show off, however a lot of work was done under the hood.  Everything has been wired for easily adding multi select (and its action menu), the overflow menu, and sort.   By "wired" I mean that the majority of the code was written and for each new view I only have to write a few lines of code to add the capabilities and then write the code to handle the actual selected actions.


This is in the album list view's presenter code (couldnt figure out a way to post code so the formatting is a bit weird).  As you can see its not much code at all to add a lot of functionality

override fun onViewAttached()

    view?.let {        addBehavior(MenuBehavior::class
, ViewModeMenuBehavior(, state))
, GridSizeMenuBehavior(, state))
, SortMenuBehavior(, state))
, AlbumSelectionBehavior())
, AlbumActionModeBehavior(it))

Anyway here are some screenshots

Friday, June 16, 2017

3.0 Work in Progress 3: Album Details + Album Grid transitions

The last 2 weeks I've been working on the album details view along with learning how to do transitions between different views.  As mentioned before I'm currently just focusing on the code portion so the actual UIs themselves are not final and still need a lot of work.

This is the current state of the album details view.  Its using the CoordinaterLayout with a collapseable toolbar, so when you scroll up the album art will basically collapse into the toolbar at the top.  I currently like how the album title moves while you scroll up and eventually becomes the title in the toolbar, but im not 100% sure if that is the direction i will go.

Below is a video that shows the transitions between selecting an album from the album grid and opening the album details.  This was recorded on an old galaxy s3 running Lineage OS (7.1.2) so it appears the actual recording is a bit glitchy.  The Image showing over half of the floating action button doesnt actually happen on the device.

Progress might seem slow but once a lot of the essential capabilities are written, they will be reusable on almost all the other views (IE artist detail view and genre detail view will be pretty similar to the album view, so it wont take long for me to add).  Next up on my list is adding the 3 dot buttons / context menus on to the list / grid items.

Friday, June 2, 2017

3.0 Work in Progress 2: Album Grid

Before I talk about my latest progress I want to reiterate that this is just a work in progress / prototype so nothing shown in the screenshots will be final.  I havent spent too much time on the UIs themselves, but have been focusing on the underlying UI code (presenters / data access / adapters / etc).  I encourage people to give feedback, however just because something is not being shown, does not mean I am getting rid of it.

Recently, google announced a bunch of new architecture libraries and since I was in the middle of some major rework, I decided to go ahead and start adapting GMMP to use these new libs.

  • Room is going to greatly simplify access GMMP's database.
  • LiveData combined with Room makes it super simple for my UI to get access to the data and get notified on changes to the database
  • ViewModel allows me to maintain UI state between orientation changes
  • Lifecycle gives my presenters access to the fragment/activity lifecycle without being tightly coupled to the fragment/activity

Google also announced official support for Kotlin in Android Studio.  I have only played around with it a little but from everything I have read it looks amazing and I do have plans to convert some of GMMP over to it.  Since its compatible with the JVM I can mix and match both kotlin and java in the same project.

Anyway for the last 2 weeks I have been working on the album view (its a standalone since I have not done anything with drawer navigation or the viewpager / tab navigation yet).  For now I have created 4 different modes for the albums list.


Card List


Card Grid

There are also nice transitions in between each view mode (and changing the number of grid columns).

I also made the metadata shown in each grid/list item configurable in the same way as now playing.  There will however be less options for the variables depending on the view (IE albums view would only give you access to the artist/album/year and not trackname variable. stuff like that).  I also added another small addition to the markup language used for the metadata lines and that is the ability to set the color.. in a very limited way.  <color=secondary> or <color=primary> can be added to each metadata line.  Primary is the whiter color and secondary is the grayer one.  For a light theme these colors would be different.  Also, each view mode will have its own metadata lines.  In the images above you will see that the list views are aligned left, but the grid views the text is aligned center.

Now Playing

There are 2 minor changes to now playing.

I made the buttons at the bottom configurable.  Besides play/pause you will be able to configure them to show other actions and also choose the icon side (small/medium/large).  In the image above I adjusted the icon sizes a bit: Shuffle/repeat are small, Next/Prev are medium, and Play/Pause is Large

Finally here is a gif if the play/pause animation:

Saturday, May 20, 2017

3.0 Work In Progress 1: New theme engine and now playing

I'd like to start off by saying that GMMP 3.0 is a long long way from being complete, but I have made some progress so I wanted to share whats been done so far.

New Theme Engine

In 2.x, GMMP had 2 main theme types: Holo and Material.  The holo themes leveraged a library called HoloAccent which reimplemented all of the UI elements in a dynamically color-able holo style.  The material themes used the android compatibility library and required each theme to be predefined in xml.  I generated roughly 1000 or so different color combinations and thats what was available to choose from.  On top of that, a lot of custom code had to be placed through out the UI code to make sure everything colored properly.

GMMP 3.0 will feature a new theme engine that will do the dynamic coloring of Material themes.  That unfortunately means there will no longer be any holo themes.  Google keeps releasing updates that break parts of that holo accent library, so I decided to drop it.  Anyway the new engine will traverse through the entire view and theme things accordingly.  It also allows me to specify different behaviors straight in the UI xml instead of in code.  (Example would be the the play/pause button using the accent color instead of the standard button color).

As of right now, a theme is defined by 6 different colors.  Primary, Primary Light, Primary Dark, Accent, Accent Dark, and Accent Light.  GMMP 3.0 will allow all 6 of these to be chosen by the user.  There will also be tons of predetermined themes available to select from for those who dont want to customize each color.

New Now Playing

The pictures above show the current state of the now playing screen.  The album art area will be where gestures are done.  I will also probably make an option to choose between having the album art extend all the way through the status bar, and having a standard colored toolbar with the album art underneath it.  The floating action button is just a placeholder currently but its purpose is going to be for quick actions.  The actions will be similar to the options available for the gesture actions.  I have not yet determined how they will be presented.

One option is the FAB to expand out to a bunch of smaller floating buttons like below:

It looks nice, but due to the location of the FAB it doesnt leave room for many buttons, so I may have to modify it to show both above and below the FAB or go down a different route all together.  The other thought i had was to make it expand out to a toolbar with buttons that sits on top of where the song information is shown.  I"ll have to prototype both to see which works better.

Below the album art is the metadata display which I will go into more detail later on in this post.  When single tapping the metadata area it will transition the UI to the queue.  I've had a lot of requests for easier queue access and it seems like this allows for that.  Perhaps a long press on that area would open up a popup with all the song details.  Finally the play/pause button will do a nice transition animation when pressed (the one where the play morphs into the pause).

Not everything mentioned here implemented yet, but that is what im shooting for.   I'll most likely do partial implementations of most of the UI views just to see how everything works together first before doing the full implementations.

Metadata View Customization

In GMMP 1.x/2.x, users were giving the option to choose from a long list of different metadata fields for each line or allowed the user to write there own custom lines using variables like %ar% (artist), %al% (album), etc.  I've greatly expanded upon this for 3.0.  There will still be presets that users can choose from if they dont want to mess with writing the lines themselves.


This has not changed.  %field% will be replaced by metadata from the tags.  The code was completely rewritten so its much more efficient this time around.  It actually parses each line instead of just doing a general replace for each field.


Entire lines or specific words in a line can be wrapped with formatting tags (there will be examples later on)

  • <align> : Aligns the text left, right, or centered.  This applies to the entire line of text
  • <b> : Bold
  • <i> : Italics
  • <size> : Text/Font size
  • <typeface> : Choose the font to use
  • <u> : Underline


Inspired by foobar2000, I've put in a few functions to allow you to apply a little logic to the lines
  • $ifequal(val1, val2, text_if_equal, text_if_not) : Compares 2 integers (val1, val2) and if they are the same it will display [text_if_equal], otherwise show [text_if_not] or nothing if that field is not specified.  
  • $ifgreater(val1, val2, text_if_greater, text_if_not) : Compares 2 integers (val1, val2) and if val > val2 it will display [text_if_greater], otherwise show [text_if_not] or nothing if that field is not specified.  
  • $notempty(val1, val2, val3, etc) : Will display the first parameter that is not empty.
All of these parameters can contain fields (which is really the only way they are useful).  More functions will probably come later, but at least right now with these 3 you can do some nice things like:  
  • Hiding disc number or track number if its 0
  • Show composer or album artist if the field is set, otherwise show artist




"<align=center><typeface=sans-serif><size=20><b>$notempty(%cp%,   ,%ar%)</b> - <i>%al%</i>"

Multiple alignments on a single line

The last customization that can be done is essentially splitting a single line into multiple segments that take up an equal percentage of the line (2 segments = 50% each or 3 segments is 33.3% each).  Each segment can get their own alignment

This is the java code representing above.  I will try to make this much more user friendly when creating lines in app

new String[]
 "<align=left><typeface=serif><size=20>$ifequal(%yr%,0,No Year,%yr%)",
new String[]
 "<align=center><typeface=serif><size=20>$ifequal(%yr%,0,No Year,%yr%)",

So thats it for now.  I will be doing more posts as things get developed

Friday, April 7, 2017


2.2.2 (04/05/2017):
-Fixed m4a crossfade bug
-Updated crashlytics to 2.6.7
-Updated support library to 25.3.1
-Updated google services to 10.2.1

Saturday, March 11, 2017


2.2.1 (03/09/2017):
-Fixed crash when executing a search with nothing but blank spaces
-New m4a decoder is now available to lollipop devices
-Fixed issue loading embedded album art when the "prefer embedded art" option was off
-Effects view now shows the correct effects when the custom audioengine is disabled
-Fixed crash on the Lenovo A6000 when raising volume above the "safe media volume"
-Other various fixes

Thursday, March 2, 2017

2.2 Released - Android Auto support & On Sale for $0.99 USD through March 12th

2.2 is finally ready to go.  Major updates were the additional of Android Auto support, a new m4a decoder (a lot of devices shipped their 6.0+ updates with broken opensl decoders, which gmmp previously used for m4a playback), and a lot of voice search improvements.  Also included are a few nice bug fixes that should improve stability.

One other thing to note is GMMP 2.2 (and 3.0 hopefully later this year) requires an android device running at least 5.0 or higher.  5.0+ represents about 80% of the active installs, so it was time to increase the minimum to take full advantage of the newer apis.

This is the playback screen when in landscape 

Menu options

More menu options (Artists, Albums, and Genres are off by default but can be enabled by turning on the Full Android Auto Access option)

Queue with the icon next to the current playing track

Playlists menu combines both smart playlists and playlist files

All Artists

Auto has the option to filter by letter


View when outside of the music player in Auto.  It has widgets for each auto app

2.2.0 (03/02/2017):
-Added Android Auto support
-Added Full Android Auto Access option in Prefs -> Library to allow access to all artists, albums, and genres
-Added new m4a/aac decoder to replace opensl on android 6.0+
-Added support for .oga extension (ogg audio)
-Added support for opus files with the .ogg or .oga extension

-Voice search refactoring/improvements
-More voice search accuracy improvements
-Added genre voice search
-Added unstructured voice search support
-Refactored data access layer
-Audiofocus is now persisted if the music service is restarted by the OS
-Playback will no longer auto resume after audiofocus loss (always play on plugin is not affected by this)
-Unlocker validation moved to the MusicService
-Updated crashlytics to 2.6.6
-Updated translations
-Improved sample rate, channel count, and duration detection
-GMMP should no longer auto resume when regaining audiofocus after a full loss (like using another player to play audio)
-Upgraded Glide to 3.7.0
-GMMP will now attempt to free up memory when the OS requests it

-The full length audio file associated with a cue will no longer show in the library views
-Fixed audioengine crash when changing tracks multiple times in a short period of time
-Fixed memory leak
-Other various minor bug fixes

-Removed support for kitkat and below
-Removed any code specific to kitkat or below
-Removed music service timeout (interferes with a lot of functionality)