function ds = datasource(whichsource, varargin)
   %DATASOURCE constructor for a datasource object.
   % The datasource object is the go-between between the waveform class (or
   % any other class) and whichever sort of database or file scheme is in use.
   %
   % ds = datasource(whichsource, filename) is the most basic implementation.
   %    Data from file FILENAME will be interpreted to be of type WHICHSOURCE.
   %
   %    default WHICHSOURCE values are 'antelope','file','sac', and 'seisan'
   %
   % ds = datasource(whichsource, fileformatstring[, param1[,...]])
   %    The FILEFORMATSTRING may have additional formatting parameters,
   %    allowing the datasource to traverse directory trees or make
   %    intelligent decisions about which files to access.  These formatting
   %    parameters follow the sprintf convetions: each starts   with a '%'
   %    followed by the type.
   %        %s : string        %f : float      %d : integer
   %      these formatters can be further modified. ex.
   %        %04d : 4-digit integer, zero padded
   %
   %      Each use of a formatter must be accompanied by a matching
   %      parameter.  See the example section, below.
   %        %d is used for  'YEAR','DAY','JDAY','HOUR','MINUTE','SECOND'
   %        %s is used for 'STATION','CHANNEL'
   %
   %        when an object is requested, the scnl, start, and end times are
   %        used to determine exactly which file(s) to consult.
   %
   % ds = datasource(interpreter_function,fileformatstring [,param1[,...]])
   %    the INTERPRETER_FUNCTION is a function handle to a user-created
   %    function capable of receiving a single filename and returning
   %    an array of objects.
   %      Ex. if I have a function declared :
   %           function objects = load_foobar(filename)
   %        then, INTERPRETER_FUNCTION would be @load_foobar
   %
   % ds = datasource('winston',servername, portnumber)
   %    this usage associates a datasource object with a winston waveserver.
   %
   % to get the default continuous antelope database, use 'uaf_continuous'
   %
   % --------------- EXAMPLES --------------------
   % *Example 1: (FILE) I would like to access a specific file of waveforms,
   % saved from matlab.
   %
   % ds = datasource('file','C:/DATA/workingfile')
   %
   % *Example 2: (ANTELOPE) the continuous waveform archive (antelope based),
   % in Fairbanks, could be set up as follows:
   %
   % ds = datasource('antelope', ...
   %      /aec/db/waveforms/%04d_%02d/waveforms_%04d_%02d_%02d',...
   %        'year','month','year','month','day');
   %
   %
   % *Example 3: (USER_DEFINED) I have a series of .CGR files stored in files
   % named for each station and Julian day, in a directory (on drive "T"named
   % for the year. I wrote my  own interpreter, a function called "load_cgr".
   %
   % ds = datasource(@load_cgr,'T:/%04d/%s%03d.cgr','year','jday','station');
   %
   %
   % *Example 4: (WINSTON) All datafiles are accessible through a winston
   % wave server, with server address myserver.uaf.edu, port 12345:
   %
   % ds = datasource('winston','myserver.uaf.edu',12345);
   %
   %
   % -------------------
   % RECOMMENDATION: commonly used datasources may best be saved saved in
   % either a .mat datafile or a .m script, where they can be loaded without
   % constantly needing to be re-entered
   %
   % more information about defining filenames and directory trees can be
   % found by typing:
   % help datasource/setfile
   %
   %
   % see also datasource/setfile
   
   % VERSION: 1.1
   % AUTHOR: Celso Reyes (celso@gi.alaska.edu)
   % LASTUPDATE: 3/26/2009
   
   ds.type=  'none';
   ds.file_string = '';
   ds.file_args = {};
   ds.server_name = '';
   ds.port_number = [];
   ds.usefile = false;
   ds.interpreter = @void_interpreter;
   ds = class(ds,'datasource');
   if nargin == 0
      return
   end
   if isa(whichsource,'function_handle')
      ds.interpreter = whichsource;
      ds.type = 'user_defined';
      if numel(varargin) == 0
         error('when setting the datasource to a user-defined type, the filesource must be declared');
      end
      ds = setfile(ds,varargin{1:end});
   else
      switch lower(whichsource)
         case 'antelope'
            switch numel(varargin)
               case 0
                  %do nothing, the default case will be handled by waveform
               otherwise
                  ds = setfile(ds,varargin{:});
                  ds.type = whichsource;
            end
            
         case {'file','sac', 'seisan', 'obspy', 'miniseed'}
            if numel(varargin) == 0
               error('when setting the datasource to %s the filesource must be declared',upper(whichsource));
            end
            ds = setfile(ds,varargin{:});
            ds.type = whichsource;
            
         case 'winston' %expect:type, databasename, port
            switch (nargin)
               case {1 2}
                  error('datasource type WINSTON requires both a server and port number');
               case 3
                  %fine
               otherwise
            end
            if ~ischar(varargin{1}),
               error('the second parameter for a WINSTON datatype must be a server name');
            end
            if ~isnumeric(varargin{2})
               error('the third parameter for a WINSTON datatype must be a port number');
            end
            ds.server_name = varargin{1};
            ds.port_number = varargin{2};
            ds.type = whichsource;
            
         case 'irisdmcws'
            ds.type = whichsource;
            
            % now, the special cases -------------------------------
            
         case 'uaf_continuous'
            %default in-house antelope databases
%             ds = datasource('antelope', ...
%                '/aerun/sum/db/archive/archive_%04d/archive_%04d_%02d_%02d',...
%                'year','year','month','day');
            ds = datasource('antelope', '/aec/db/waveforms/%04d_%02d/waveforms_%04d_%02d_%02d',...
               'year','month','year','month','day');
            
         case 'uaf_continuous_op'
            %default in-house antelope databases (prior to July 2011)
            ds = datasource('antelope', ...
               '/iwrun/op/db/archive/archive_%04d/archive_%04d_%02d_%02d',...
               'year','year','month','day');
            % end special cases ------------------------------------
            
         otherwise
            error('Current valid datasources are: ANTELOPE, SAC, FILE, WINSTON, SEISAN, OBSPY, or a function handle to an interpeter function');
      end
   end
end
