citruspi / Spotify-Notifications

Bridging Spotify and macOS Notification Center
https://spotify-notifications.citruspi.io
645 stars 63 forks source link

Enhancement - Show Progress of Song #36

Open ianpgall opened 9 years ago

ianpgall commented 9 years ago

When I listen to music or watch videos, I have a problem - I need to constantly know how much of their time has elapsed (out of their total length).

So, my main proposal is that somehow, you add the elapsed time and the total time of the song to the notification (if it's even possible).

Obviously, this isn't very useful as soon as a song changes and the notification is shown (other than seeing the total length of the song), but is very useful in my opinion when you use the keyboard shortcut, which I do a lot.

I know the notification is shown for a few seconds, so that gives potential for the elapsed time to change, but I don't think it's worth the effort (I have a feeling it wouldn't be easy). I imagine it that as soon as the notification is to be shown, the elapsed and total time are recorded and those values are statically shown until a new notification is requested.

citruspi commented 9 years ago

@ianpgall,

I can see the appeal of being able to see the elapsed time.

I'd probably implement so that if the notification was dispatched because of a play state change, it would simply include the total track length. If the notification was dispatched because the keyboard shortcut was pressed, it would include the elapsed time and the track length.

Would that be fine? Or would you want to see both so that if the play state changes mid-track it includes the elapsed time?

Having said that, I'm not even sure how this would be implemented. When a new track is played, Spotify provides the track length, but not the elapsed time.

Any ideas?

— @citruspi

citruspi commented 9 years ago

@ianpgall,

Idea.

When the play state changes and it's a new track being played set the elapsed time to zero. Create a stopwatch in the background and start it.

When the play state changes and the track is being paused, pause the stopwatch. When the play state changes and the same track is being played, start the stopwatch.

This wouldn't work if the user manually changed their place in the track via the Spotify client. The elapsed time would change and I wouldn't be able to know that it changed, let alone where it is now.

Also, it would be a messy implementation overall. Just an idea.

— @citruspi

ianpgall commented 9 years ago

@citruspi Honestly whatever you could come up with, would be awesome. I just thought it would be easy to handle more generically, so that you always show the elapsed time (if you could get it), and not have to distinguish between play state change and keyboard shortcut (it could get done sooner, and less complexity in the code). It's unfortunate to hear Spotify doesn't provide the elapsed time; I wasn't sure what it provided and how you got the data anyways.

The stopwatch idea is definitely a good workaround if you can't get the elapsed time directly, but because of the ability to manually change their place, it doesn't seem enough. Also, because of any delays between Spotify and your app, the estimated elapsed time could get pretty inaccurate if not done properly (still, we're only talking milliseconds or seconds at the most).

Ever since I found this project, I was interested in how it worked. I've never written code for Apple products, nor interacted directly with a non-proprietary application or its API. Is there any guide/references you can provide for how to interact with Spotify like you have? I tried looking at your code but I'm just lost. And I tried to look on their developer website, but it didn't look like there was anything specifically in reference to what you're interacting with (I'm probably wrong though...or maybe I'm just misunderstanding how the project works and am looking in the wrong places).

I'd love to contribute, whether it actually be with code, or just guidance, but I'm afraid I'm inexperienced in this area.

citruspi commented 9 years ago

@ianpgall,

Is there any guide/references you can provide for how to interact with Spotify like you have?

Basically, whenever the play state on the Spotify client changes, Spotify sends a notification to the NSDistributedNotificationCenter. Spotify Notifications listens for these notifications.

Whenever we receive a notification that the play state has changed, we check if playback started or stopped. The notification includes some information like the track's title, artist, album, ID, etc. We create a new notification with this information. We also query the API with the ID and parse the location of the album art.

Once we have the notification set up, we dispatch it to Notification Center.

I tried looking at your code but I'm just lost.

That's completely my fault. Over time the code has gotten a little messy and I was never the best at consistently commenting. In a week or two, once my workload has been reduced, I'll probably make a go at cleaning up the project with cleaner code, better organization, and more comments. Perhaps I'll even rewrite it in Swift.

And I tried to look on their developer website, but it didn't look like there was anything specifically in reference to what you're interacting with...

Spotify provides some SDK's and API's. Aside from the API to fetch the location of album art, the project doesn't make use of them. When I first wrote it, there was no need to use the native SDK - everything I wanted was included in the play state notification.

I'd love to contribute, whether it actually be with code, or just guidance, but I'm afraid I'm inexperienced in this area.

No worries. I'd also consider myself inexperienced - I'm primarily a Python and Go developer. This is the only Objective-C project which I've stuck with beyond a week, because, well I actually needed it. I'm learning Objective-C and the OS X SDK through this project.

So feel free to contribute in any way you're comfortable. Pull requests and issues are always welcome.

— @citruspi

citruspi commented 9 years ago

@ianpgall,

Honestly whatever you could come up with, would be awesome.

Completely agree, this would be a cool feature if implemented correctly.

To be honest, I don't have the time or resources to look into it in the next week or two. When I do get some free time, I'll dig around and see if I can determine a "non-hacky" way to implement it.

Cheers.

— @citruspi

ianpgall commented 9 years ago

@citruspi Sorry, when I said that I was lost when looking at your code, I didn't mean at all because of your organization or quality, or actual code. 100% I was referring to the fact that it's C, and an OS X project. I "know" C, but I definitely don't know how to write C projects, especially ones for OS X. I come from JavaScript/Java/Python/.NET, and I know how their projects are normally structured, I know where to look for stuff, and how different files interact with each other. Even for such a seemingly "simple" project, I think I just feel overwhelmed because of it being C.

Maybe I'm over-exaggerating on how hard it is to read the project, so I'll just go back to looking it all over. Is there a "starting point" in your project - some file that everything else kinda stems from? In Java, I think of the "public static void main()" or C++ "int main()" methods. Anything like that here?

Thanks for the response and resources, I'll definitely look into that stuff - it makes sense at a high level, I just need to learn more on a lower level. Like I said, I just haven't done this type of development, so I was a little lost getting into the project.

And please, no rush or obligation, it was just a suggestion because of my OCD :) Thanks!

citruspi commented 9 years ago

@ianpgall,

Sorry, when I said that I was lost when looking at your code, I didn't mean at all because of your organization or quality, or actual code.

That may be the case, but I should definitely organize it better and write comments. :wink:

Is there a "starting point" in your project - some file that everything else kinda stems from? In Java, I think of the "public static void main()" or C++ "int main()" methods. Anything like that here?

It may look like a lot of files, but if you open it in Xcode it'll look like this:

The only files which I actually write are

Everything else is part of some library I'm using.

Technically it all starts in main.m in the main method, but for our purposes, it starts on line 42 of AppDelegate.m in

- (void)applicationDidFinishLaunching:(NSNotification *)notification

In there I check the operating system version, read and set preferences, and subscribe to play state notifications from Spotify. The rest of AppDelegate.m is primarily

— @citruspi

sebj commented 7 years ago

@citruspi SpotifyApplication exposes a playerPosition property we could read, in combination with the duration of the song. Wouldn't mind adding ("1:39 / 4:10") or something similar to the keyboard shortcut notification. My only question would be: show the time by default when the shortcut is pressed, or have a preferences option to show it? (I'd vote former)

citruspi commented 7 years ago

Thanks for taking a look into this @sebj!

So currently the notification is

<title>
<album>
<artist>

Where would you see the playerPosition and duration being positioned?

My first instinct is to say to the right of the title, like

<title> ("<position> / <duration>")
<album>
<artist>

but with longer titles, the position and duration information would just disappear.

screen shot 2017-01-03 at 8 37 08 am

I think a preferences option to show it is in order either way, the question is whether it should be enabled by default or not. Do you think that the majority (i.e. > 50%) of our users would want/find this information useful? If not, I'd vote for it to be disabled by default.

If we're not sure, it might be useful to ping some other contributors or gather feedback from users (talk to some friends or something?).

sebj commented 7 years ago

@citruspi I hadn't thought about time info with longer titles actually.. We could re-arrange the notification information to match the title and subtitle format of iTunes when the preferences option is enabled, and add time after, like:

<title>
<artist> — <album>
<position> / <duration>

I'd also vote for the preferences option to be disabled by default (not sure the majority of users would find the info useful).

citruspi commented 7 years ago

We could re-arrange the notification information to match the title and subtitle format of iTunes when the preferences option is enabled

Cool, so just to cover the formats for different scenarios:

  1. Triggered by Spotify Event Change and Preference Disabled
<title>
<album>
<artist> 
  1. Triggered by Spotify Event Change and Preference Enabled
<title>
<artist> — <album>
  1. Triggered by Global Shortcut and Preference Disabled
<title>
<album>
<artist> 
  1. Triggered by Global Shortcut and Preference Enabled
<title>
<artist> — <album>
<position> / <duration>

Alternately, I'd also be comfortable with changing the format to

<title>
<artist> — <album>

regardless of whether the preference is enabled or not and then adding the third line with the position and duration if the preference is enabled.

In which case there would only be three scenarios to cover:

  1. Triggered by Spotify Event Change
<title>
<artist> — <album>
  1. Triggered by Global Shortcut and Preference Disabled
<title>
<artist> — <album> 
  1. Triggered by Global Shortcut and Preference Enabled
<title>
<artist> — <album>
<position> / <duration>
sebj commented 7 years ago

@citruspi Y'know I was just going to ask that too. I see iTunes, Miniplay, and possibly others following that format. Those 3 scenarios sound good to me.

ianpgall commented 7 years ago

@sebj @citruspi Just wanted to thank you for looking into this. You guys seemed to have figured out the layout/structure, but I figured I'd just give a little input.

I agree that the display of elapsed time should be configurable, and be turned off by default.

I think the 3 scenarios/formats look good, but I wonder if scenario 2 does exist, and simply only lists the track's total time on the 3rd line. Would that make sense? Or I wonder if there's more scenarios (now I'm just being picky). For example, if the song has been played any amount but it's paused and you press the "play" button on your keyboard, a notification pops up. So I personally would want the elapsed time and total time to show on that 3rd line (of course, only if I have the setting enabled). Or if the track changes to a new one, a notification pops up - in that case, I'd want to see the total time. There could be slightly more logic so that if the elapsed time is 0 (song just started), don't show the elapsed time (but still show the total time). I think I'm getting picky, but that's how I imagine it, now that you've discussed the different scenarios. Definitely feel free to implement it however; I know any mention of elapsed/total times would be awesome.

I'm really excited to see how this turns out. I'd be happy to help, just not sure what I could do without any OS X development experience. I'll start looking in the code again (and citruspi's older explanations above) to see if I can understand what would be changed, but let me know how I can help.

Thanks!