#region CPL License
/*
Nuclex Framework
Copyright (C) 2002-2009 Nuclex Development Labs
This library is free software; you can redistribute it and/or
modify it under the terms of the IBM Common Public License as
published by the IBM Corporation; either version 1.0 of the
License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
IBM Common Public License for more details.
You should have received a copy of the IBM Common Public
License along with this library
*/
#endregion
using System;
using System.Collections.Generic;
using Nuclex.Support.Tracking;
namespace Nuclex.Audio.Metadata {
/// Connection to a CDDB compatible database server
public class CddbConnection : IDisposable {
#region struct ServerProtocolLevel
///
/// Stores the active and, if available, maximum supported protocol level
/// of a CDDB server
///
public struct ServerProtocolLevel {
/// Initializes a new CDDB server protocol level structure
/// Active server protocol level to store
///
/// Maximum support server protocol level to store
///
public ServerProtocolLevel(
int activeProtocolLevel,
int? supportedProtocolLevel
) {
this.ActiveProtocolLevel = activeProtocolLevel;
this.SupportedProtocolLevel = supportedProtocolLevel;
}
/// Protocol level currently used by the CDDB server
public int ActiveProtocolLevel;
/// Maximum protocol level the CDDB server supports
public int? SupportedProtocolLevel;
}
#endregion // struct ServerProtocolLevel
/// Initializes a new CDDB server connection
/// Protocol by which the CDDB server can be reached
/// Host name of the connected CDDB server
/// Version of the CDDB software running on the server
/// Whether the server has restricted us to read access
internal CddbConnection(
CddbProtocol protocol, string hostname, string version, bool readOnly
) {
this.protocol = protocol;
this.hostname = hostname;
this.version = version;
this.readOnly = readOnly;
// This is not documented in the CDDB protocol specification, but all servers
// I tested it with begin a new connection with protocol level 1. This also
// is the only valid choice if the server wants to keep backward compatibility.
this.activeProtocolLevel = 1;
}
/// Immediately releases all resources owned by the instance
public void Dispose() {
if(this.protocol != null) {
this.protocol.Dispose();
this.protocol = null;
}
}
/// Logs out from the server and closes the connection
/// A request by which the log out process can be tracked
///
/// You should call this method and wait for the request to finish before
/// disposing of the connection to gracefully leave the CDDB server.
///
public Request Quit() {
Requests.CddbQuitRequest request = new Requests.CddbQuitRequest(
this.protocol
);
request.Start();
return request;
}
/// Lists the genre categories known to the CDDB server
/// A request that will provide the genre list upon completion
public Request ListCategories() {
Requests.CddbCategoryListRequest request = new Requests.CddbCategoryListRequest(
this.protocol
);
request.Start();
return request;
}
/// Retrieves the protocol level currently used by the CDDB server
///
/// A request that will provide the active protocol level upon completion
///
public Request GetProtocolLevel() {
Requests.CddbProtocolLevelRequest request = new Requests.CddbProtocolLevelRequest(
this.protocol
);
request.Start();
return request;
}
/// Changes the protocol level used by the CDDB server connection
/// New protocol level to switch to
///
/// A request that will indicate when the protocol level has been changed
///
public Request ChangeProtocolLevel(int newLevel) {
Requests.CddbProtocolLevelRequest request = new Requests.CddbProtocolLevelRequest(
this.protocol,
newLevel,
new Requests.CddbProtocolLevelRequest.ProtocolLevelNotificationDelegate(
protocolLevelChanged
)
);
request.Start();
return request;
}
///
/// Queries the CDDB server for informations about the specified disc
///
/// Total length of the CD in seconds
///
/// Track offsets, in seconds, for each track of the CD
///
/// A request that will provide the query results upon completion
public Request Query(
int discLengthSeconds, int[] trackOffsetsSeconds
) {
Requests.CddbQueryRequest request = new Requests.CddbQueryRequest(
this.protocol, discLengthSeconds, trackOffsetsSeconds
);
request.Start();
return request;
}
/// Reads the CDDB entry for the specified CD
/// Category in which the CD's CDDB entry is stored
/// Disc id of the CD whose CDDB entry will be read
/// A request that will provide the CDDB entry upon completion
///
/// The CDDB specification requires you to first execute a query and only then
/// use the read command to retrieve a database file. Otherwise, the data being
/// returned is undefined.
///
public Request Read(string category, int discId) {
Requests.CddbReadRequest request = new Requests.CddbReadRequest(
this.protocol, category, discId
);
request.Start();
return request;
}
/// Hostname of the server to which the connection was made
public string Hostname {
get { return this.hostname; }
}
/// Version of the CDDB software running on the server
public string Version {
get { return this.version; }
}
///
/// Whether the client has been restricted to read access by the server
///
public bool ReadOnly {
get { return this.readOnly; }
}
/// Currently active protocol level for the connection
public int ProtocolLevel {
get { return this.activeProtocolLevel; }
}
/// Called when the active protocol level has been changed
/// New protocol level the connection is using
private void protocolLevelChanged(int newLevel) {
bool wasUtf = (this.activeProtocolLevel >= 6);
bool isUtf = (newLevel >= 6);
this.activeProtocolLevel = newLevel;
if(wasUtf != isUtf) {
this.protocol.UseUtf8 = isUtf;
}
}
/// Protocol used to communicate with the CDDB server
private CddbProtocol protocol;
/// Hostname the server reported in the greeting string
private string hostname;
/// Version of the CDDB software supposedly running on the server
private string version;
/// Whether this client is in read-only mode
private bool readOnly;
/// Currently active protocol level for the connection
private volatile int activeProtocolLevel;
}
} // namespace Nuclex.Audio.Metadata