public SpotifyConnection(ICache cache, TimeSpan timeout) { this.session = new Session(); this.protocol = null; this.running = false; this.user = null; this.userSemaphore = new Semaphore(0, 2); this.cache = cache; this.timeout = timeout; }
/// <summary> /// Login to Spotify using the specified username and password. /// </summary> /// <param name="username">Username to use.</param> /// <param name="password">Corresponding password.</param> public void Login(string username, string password) { if (this.protocol != null) { throw new InvalidOperationException("Already logged in!"); } this.protocol = this.session.Authenticate(username, password); this.user = new Sharpotify.Media.User(username); this.protocol.AddListener(this); /*Start the thread*/ /*It only runs one time, then it stops. The first asyncronous call is needed :)*/ System.Threading.Thread backgroundProcess = new System.Threading.Thread(delegate() { this.Run(); }); backgroundProcess.Name = "Sharpotify.Background"; backgroundProcess.IsBackground = true; backgroundProcess.Start(); }
public void CommandReceived(int command, byte[] payload) { byte[] aux; switch (command) { case Command.COMMAND_SECRETBLK: /* Check length. */ if (payload.Length != 336) { System.Console.WriteLine("Got command 0x02 with len " + payload.Length + ", expected 336!\n"); } /* Check RSA public key. */ byte[] rsaPublicKey = this.session.RSAPublicKey.ToByteArray(); for (int i = 0; i < 128; i++) { if (payload[16 + i] != rsaPublicKey[i]) { System.Console.WriteLine("RSA public key doesn't match! " + i + "\n"); break; } } /* Send cache hash. */ try { this.protocol.SendCacheHash(); } catch (ProtocolException) { /* Just don't care. */ } break; case Command.COMMAND_PING: /* Ignore the timestamp but respond to the request. */ /* int timestamp = IntegerUtilities.bytesToInteger(payload); */ try { this.protocol.SendPong(); } catch(ProtocolException) { /* Just don't care. */ } break; case Command.COMMAND_PONGACK: break; case Command.COMMAND_CHANNELDATA: Channel.Process(payload); break; case Command.COMMAND_CHANNELERR: Channel.Error(payload); break; case Command.COMMAND_AESKEY: aux = new byte[payload.Length - 2]; Array.Copy(payload, 2, aux, 0, aux.Length); /* Channel id is at offset 2. AES Key is at offset 4. */ Channel.Process(aux); break; case Command.COMMAND_AESKEYERR: aux = new byte[payload.Length - 2]; Array.Copy(payload, 2, aux, 0, aux.Length); /* Channel id is at offset 2. */ Channel.Error(aux); break; case Command.COMMAND_SHAHASH: /* Do nothing. */ break; case Command.COMMAND_COUNTRYCODE: //System.out.println("Country: " + new String(payload, Charset.forName("UTF-8"))); this.user.Country = new RegionInfo(Encoding.UTF8.GetString(payload)); /* Release 'country' permit. */ this.userSemaphore.Release(); break; case Command.COMMAND_P2P_INITBLK: /* Do nothing. */ break; case Command.COMMAND_NOTIFY: /* HTML-notification, shown in a yellow bar in the official client. */ /* Skip 11 byte header... */ /*System.out.println("Notification: " + new String( Arrays.copyOfRange(payload, 11, payload.length), Charset.forName("UTF-8") ));*/ aux = new byte[payload.Length - 11]; Array.Copy(payload, 11, aux, 0, payload.Length - 11); this.user.Notification = Encoding.UTF8.GetString(aux); break; case Command.COMMAND_PRODINFO: this.user = XMLUserParser.ParseUser(payload, this.user); /* Release 'prodinfo' permit. */ this.userSemaphore.Release(); break; case Command.COMMAND_WELCOME: break; case Command.COMMAND_LICENSE: break; case Command.COMMAND_PAUSE: /* TODO: Show notification and pause. */ break; case Command.COMMAND_PLAYLISTCHANGED: System.Console.WriteLine("Playlist '" + Hex.ToHex(payload) + "' changed!\n"); break; default: System.Console.WriteLine("Unknown Command: 0x" + command.ToString("X2") + " Length: " + payload.Length + "\n"); System.Console.WriteLine("Data: " + Encoding.UTF8.GetString(payload) + " " + Hex.ToHex(payload)); break; } }