rahims / SoCo

SoCo (Sonos Controller) is a simple Python class that allows you to programmatically control Sonos speakers.
331 stars 33 forks source link

added pandora radio service and ability to get user account. Code needs some optimisation most likely #35

Closed scottgwaters closed 11 years ago

scottgwaters commented 11 years ago

Mainly putting this here so others can see if it works. If someone could look through some of the functions that would be great. It works and you can try it with this

#!/usr/bin/env python
from soco import SoCo
from soco import SonosDiscovery

if __name__ == '__main__':

    sonos = SoCo('192.168.1.59') # Pass in the IP of your Sonos speaker

    pandora_email = sonos.get_music_service_email('Pandora')
    pandora_stations = sonos.get_pandora_stations(pandora_email)

    station_selector = {}
    counter = 1
    for station in pandora_stations:
        print counter,"-", station
        station_selector[counter] = station
        counter +=1
    station_selection = int(raw_input("Please select station by number:"))

    selected_station_name = station_selector[station_selection]
    selected_station_id = pandora_stations[selected_station_name]

    sonos.play_music_station('Pandora', selected_station_name, selected_station_id, pandora_email)
    sonos.play()
phut commented 11 years ago

Cannot try this out for lack of pandora - but it looks to use the same magic as Tunein and the Play Queue - and I would guess by extension all of the other services for both getting the station list and for starting playback. I don't think it will take a lot to re-factor SoCo to have a general "iterate service" and "play service" functions rather then adding them piecemeal (I've already done it to some extent in my very hacky code)

DPH commented 11 years ago

Same for me - sorry - no Pandora in the UK Agree @phut would be nice to have a generic solution. Cheers Daivd

KennethNielsen commented 11 years ago

Hallo @scottgwaters

It looks like you put quite a bit of work into this. I'm afraid I can't test it either, but I'd be happy to give some feedback.

About what @phut and @DPH said I agree, to the extent that it is possible it would be nice to have a generic solution if it is possible.

That being said, I'm not sure that it will be possible in general, so therefore I have started creating the general plugin frame work I mentioned in the other thread. This will allow us to create general music service plugings for soco and switch between them. The purpose of it will be to contain the code relating to a single file in a subfolder as to not make the base dir to cluttered. The second thing that it will do is to not add any extra code to the main SoCo class besides two functions to load and get the plugin. It think that it would work nicely and that your pandora code would fit well within that framework, if you like. We will see, I'll post it soon.

Regarding your specific code: SoCoPandora.py: Line 14. In general I think it would be very nice if we would be able to get as much information from the sonos units as possible. The idea is that the pandora people will probably keep the pluging up to date and therefore make sure that it works if they change something in the website, whereas our code might stop working if it relies on parsing information from their website.

Line 20. Same thing, even though that link looks more general.

getMusicServices.py The code in this file seems like it would do nicely as a general function in SoCo.

getpandorastations.py I guess this does some of the same things as the code in SoCoPandora.py and again I would say that it would be better if we could get the list of stations for your user directly from sonos, but I'm not sure if it is possible.

getpandorausername(.py) Seem to fit in as a method in a pandora class, with the same comment as above about getting information from sonos.

soco.py get_music_service_email The question is whether there might be more relevant information to send back than just the email, given that it is put into an appropriate data structure. There is a typo in music_serice_to_find

play_music_station Looks nice, all though it would be rocking to see if it could be generalized to cover more services. Maybe also in the long run all the service info could be factored out.

get_pandora_stations As per my previous comment, since this function directly uses the service website it will be service specific and I therefore think that it should be factored out into a plugin.

__get_music_service_settings Looks nice. I think line 977 is a little to much of a one lines, and also that if you want to change the data structure, lets get it done right away.

I hope you can use the comments. Regards and keep up the good work. Kenneth

scottgwaters commented 11 years ago

@KennethNielsen Thanks for the time you put into the feedback. Pandora is different than the other radio services on Sonos where it actually requires getting the information from Pandora. Sonos is pulling this information directly from the website. I know there are a few others that are like that as well.

The early music services did not use Sonos new architecture so I think anything in single digits as a music service number is handled differently then say spotify which was done later. That is the next service I'm going to look into after I make some of the changes you suggest. I am going to write up a wiki on how I obtained this information. Have you used wireshark at all? http://www.wireshark.org/ It's been really helpful in figuring this out. I just play a station or use the controller on my computer and capture all the data sent from the Sonos app to the player.

What I found with Pandora is it doesn't take the information from the player at all it pulls it from the web. tuner.pandora.com specifically. This actually requires authentication to log in. There is a python pandora library that seems to emulate an Android device. https://github.com/02strich/python-pandora

KennethNielsen commented 11 years ago

Ahh ok, I wasn't aware of that this service pull its information directly from the web. That takes care of like half of my comments.

I have never used wireshark but I'll look forward to wiki page. I was wondering if special hardware is required?

In any case. I still think we should consider putting all the pandora specific code into a plugin of sorts, so that SoCo doesn't explode in size. I have made that framework that I was talking about here: https://github.com/rahims/SoCo/pull/41. If it gets pulled and if you think it is a good idea then we could use that. I'd be happy to help if you need it.

scottgwaters commented 11 years ago

No special hardware is needed for wireshark. Can you run sonos with wine? Trying to trace tcp packets not comping from the computer is a little harder and I'm not sure how to do it. The majority of music services will get their information from the sonos just some of the very first ones will need to authenticate with the services websitee

DPH commented 11 years ago

Agree Wireshark http://www.wireshark.org/ is great for trying to track what is going on - free open source packet analyzer, supposedly cross platform - I use if on windows 7 with no extra hardware. I am still learning it - takes some time - easiest way I have found it to capture packets for a short time, and then use Find (in the pop up select String and Packet bytes + what you are searching for). Attached a picture but not sure if it will follow through. wireshark2

KennethNielsen commented 11 years ago

Hallo @scottgwaters I look forward to that wiki page.

If I understood you correctly this pull request was mostly about getting feedback. Would it be ok if we closed it and then you can resubmit at the new location when it is in the state that you want it?