/// <summary> /// Initializes a new CDDB protocol level request for changing of /// the current protocol level /// </summary> /// <param name="protocol"> /// Protocol used to communication with the CDDB server /// </param> /// <param name="newLevel">New protocol level that will be set</param> /// <param name="callback"> /// Callback to be invoked as soon as the new protocol level is set /// </param> public CddbProtocolLevelRequest( CddbProtocol protocol, int newLevel, ProtocolLevelNotificationDelegate callback ) { this.protocol = protocol; this.newLevel = newLevel; this.callback = callback; }
/// <summary>Queries the server for its active protocol level</summary> private void queryProtocolLevel() { // Issue the command to the CDDB server this.protocol.SendLine("proto", 5000); // Receive the reply from the server string statusLine = this.protocol.ReceiveLine(5000); // Obtain the status code returned by the server int statusCode = CddbProtocol.GetStatusCode(statusLine); // Decode the server reply switch(statusCode) { case 200: { this.protocolLevel = decodeDetailedProtocolLevel(statusLine); break; } case 201: { this.protocolLevel = decodeShortProtocolLevel(statusLine); break; } default: { this.exception = exceptionFromProtocolStatus( statusCode, statusLine.Substring((statusLine.Length >= 4) ? 4 : 3) ); break; } } }
/// <summary>Called asynchronously to execute the request</summary> /// <param name="state">Not used</param> private void execute(object state) { lock(this.protocol.SyncRoot) { try { this.protocol.SendLine( string.Format("cddb read {0} {1:x8} ", this.category, this.discId), 5000 ); // The first reply will indicate the status of the request. string statusLine = this.protocol.ReceiveLine(5000); int statusCode = CddbProtocol.GetStatusCode(statusLine); switch(statusCode) { case 210: { this.results = receiveDatabaseFile(); break; } default: { this.exception = exceptionFromQueryStatus( statusCode, statusLine.Substring((statusLine.Length >= 4) ? 4 : 3) ); break; } } } catch(Exception exception) { if(!(this.exception is AbortedException)) { this.exception = exception; } } } OnAsyncEnded(); }
/// <summary>Initializes a new CDDB database read request</summary> /// <param name="protocol"> /// Protocol used to communication with the CDDB server /// </param> /// <param name="category">Category in which the CD's CDDB entry is stored</param> /// <param name="discId">Disc id of the CD whose CDDB entry will be read</param> public CddbReadRequest( CddbProtocol protocol, string category, int discId ) { this.protocol = protocol; this.category = category; this.discId = discId; }
/// <summary>Called asynchronously to execute the request</summary> /// <param name="state">Not used</param> private void execute(object state) { lock(this.protocol.SyncRoot) { try { this.protocol.SendLine("quit", 5000); // The first reply will indicate the status of the request. string statusLine = this.protocol.ReceiveLine(5000); int statusCode = CddbProtocol.GetStatusCode(statusLine); switch(statusCode) { case 230: { break; } default: { this.exception = exceptionFromQueryStatus( statusCode, statusLine.Substring((statusLine.Length >= 4) ? 4 : 3) ); break; } } } catch(Exception exception) { this.exception = exception; } // Close the connection, whether an error occured or not this.protocol.Dispose(); } OnAsyncEnded(); }
/// <summary>Initializes a new CDDB disc query request</summary> /// <param name="protocol"> /// Protocol used to communication with the CDDB server /// </param> /// <param name="discLengthSeconds"> /// Total length of the CD (from the beginning of the first track to the end of the /// last track) in seconds /// </param> /// <param name="trackOffsetsSeconds"> /// Offsets of the individual tracks on the CD in seconds /// </param> public CddbQueryRequest( CddbProtocol protocol, int discLengthSeconds, int[] trackOffsetsSeconds ) { this.protocol = protocol; this.discLengthSeconds = discLengthSeconds; this.trackOffsetsSeconds = trackOffsetsSeconds; }
/// <summary>Aborts the running process. Can be called from any thread.</summary> /// <remarks> /// The receiver should honor the abort request and stop whatever it is /// doing as soon as possible. The method does not impose any requirement /// on the timeliness of the reaction of the running process, but implementers /// are advised to not ignore the abort request and urged to try and design /// their code in such a way that it can be stopped in a reasonable time /// (eg. within 1 second of the abort request). /// </remarks> public void AsyncAbort() { if(this.protocol != null) { CddbProtocol theProtocol = this.protocol; this.protocol = null; theProtocol.Dispose(); } }
/// <summary>Receives the repy to the 'hello' and validates it</summary> private void receiveHelloReply() { string replyLine = this.protocol.ReceiveLine(5000); int statusCode = CddbProtocol.GetStatusCode(replyLine); this.exception = exceptionFromHelloResponseStatus( statusCode, replyLine.Substring((replyLine.Length >= 4) ? 4 : 3) ); }
/// <summary>Aborts the running process. Can be called from any thread.</summary> /// <remarks> /// The receiver should honor the abort request and stop whatever it is /// doing as soon as possible. The method does not impose any requirement /// on the timeliness of the reaction of the running process, but implementers /// are advised to not ignore the abort request and urged to try and design /// their code in such a way that it can be stopped in a reasonable time /// (eg. within 1 second of the abort request). /// </remarks> public void AsyncAbort() { if(this.protocol != null) { CddbProtocol theProtocol = this.protocol; this.protocol = null; this.exception = new AbortedException("Aborted on user request"); theProtocol.Dispose(); } }
/// <summary> /// Performs the client/server handshake upon connecting to a CDDB server /// </summary> /// <param name="status">Not used</param> private void performClientServerHandshake(object status) { try { this.protocol = new CddbProtocol(this.socket); // Receive the server greeting string. This is sent by the CDDB server to // any client as soon as it connects and contains the server status and // software running on the server string greetingLine = this.protocol.ReceiveLine(5000); OnProgressAchieved(0.6f); // Obtain the status code returned from the server and convert it to // an exception if it indicates an error int greetingStatusCode = CddbProtocol.GetStatusCode(greetingLine); this.exception = exceptionFromGreetingStatus( greetingStatusCode, greetingLine.Substring((greetingLine.Length >= 4) ? 4 : 3) ); // If no error has occured, decode the server greeting string if(this.exception == null) { ServerGreeting greeting = decodeServerGreeting(greetingLine); // The server greeting was decoded successfully, now let's identify ourselves // to the CDDB server sendHello(); OnProgressAchieved(0.8f); // Receive the reply to our 'hello' from the server receiveHelloReply(); // If everything went fine the CDDB connection is ready to enter normal service if(this.exception == null) { this.connection = new CddbConnection( protocol, greeting.Hostname, greeting.Version, (greetingStatusCode == 201) // Read only connection? ); } } } catch(ObjectDisposedException exception) { if(!(this.exception is AbortedException)) { this.exception = exception; } } catch(Exception exception) { this.exception = exception; } OnAsyncEnded(); }
/// <summary>Called asynchronously to execute the request</summary> /// <param name="state">Not used</param> private void execute(object state) { lock(this.protocol.SyncRoot) { try { sendQuery(); // The first reply will indicate the status of the request. string statusLine = this.protocol.ReceiveLine(5000); int statusCode = CddbProtocol.GetStatusCode(statusLine); switch(statusCode) { case 200: { // Exact match found this.results = new Cddb.Disc[1] { decodeDiscFromStatusLine(statusLine) }; break; } case 202: { // No matches found this.results = new Cddb.Disc[0]; break; } case 211: { // Inexact matches found this.results = receiveDiscs(); break; } default: { this.exception = exceptionFromQueryStatus( statusCode, statusLine.Substring((statusLine.Length >= 4) ? 4 : 3) ); break; } } } catch(Exception exception) { if(!(this.exception is AbortedException)) { this.exception = exception; } } } OnAsyncEnded(); }
/// <summary>Changes the CDDB server's active protocol level</summary> private void changeProtocolLevel() { // Issue the command to the CDDB server this.protocol.SendLine(string.Format("proto {0}", this.newLevel.Value), 5000); // Receive the reply from the server string statusLine = this.protocol.ReceiveLine(5000); // Obtain the status code returned by the server int statusCode = CddbProtocol.GetStatusCode(statusLine); // Decode the server reply switch(statusCode) { case 200: { this.protocolLevel = decodeDetailedProtocolLevel(statusLine); break; } case 201: { this.protocolLevel = decodeShortProtocolLevel(statusLine); break; } default: { this.exception = exceptionFromProtocolStatus( statusCode, statusLine.Substring((statusLine.Length >= 4) ? 4 : 3) ); return; } } // Because we're pedantic, we'll check whether the server actually reported // the new protocol level we requested back to us. if(this.newLevel.Value != this.protocolLevel.ActiveProtocolLevel) { this.exception = new BadResponseException( "Server sent a positive response but didn't change the protocol level" ); } else { // Everything went well this.callback(this.newLevel.Value); } }
/// <summary>Called asynchronously to execute the request</summary> /// <param name="state">Not used</param> private void execute(object state) { lock(this.protocol.SyncRoot) { try { // Issue the command to the CDDB server this.protocol.SendLine("cddb lscat", 5000); // The first reply will indicate the status of the request. string statusLine = this.protocol.ReceiveLine(5000); int statusCode = CddbProtocol.GetStatusCode(statusLine); // Process the response according to its status code switch(statusCode) { // Request was accepted and genre list follows case 210: { this.categories = receiveCategoryList(); break; } // No success code, find out what exactly went wrong default: { this.exception = exceptionFromGenreListStatus( statusCode, statusLine.Substring((statusLine.Length >= 4) ? 4 : 3) ); break; } } } catch(Exception exception) { this.exception = exception; } } OnAsyncEnded(); }
/// <summary> /// Initializes a new CDDB protocol level request for retrieval of /// the current protocol level /// </summary> /// <param name="protocol"> /// Protocol used to communication with the CDDB server /// </param> public CddbProtocolLevelRequest( CddbProtocol protocol ) { this.protocol = protocol; }
/// <summary>Initializes a new CDDB quit request</summary> /// <param name="protocol"> /// Protocol used to communication with the CDDB server /// </param> public CddbQuitRequest(CddbProtocol protocol) { this.protocol = protocol; }
/// <summary>Initializes a new CDDB category list request</summary> /// <param name="protocol"> /// Protocol used to communication with the CDDB server /// </param> public CddbCategoryListRequest(CddbProtocol protocol) { this.protocol = protocol; }