Module: AppConfig

Included in:
Dvdprofiler2xbmc::CLI
Defined in:
lib/dvdprofiler2xbmc/app_config.rb

Overview

Synopsis

This module encapsulates the application’s config hash by adding default, load, and save methods. Also behaves as a global hash, meaning you can access it from anywhere in your code like:

AppConfig[:images_dir]

or

AppConfig['images_dir']

Note this is because the implementation is a Mash instead of a Hash and does cause a limitation where the key must be either a symbol or a string.

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.configObject (readonly)

Returns the value of attribute config.



51
52
53
# File 'lib/dvdprofiler2xbmc/app_config.rb', line 51

def config
  @config
end

.data_typeObject (readonly)

Returns the value of attribute data_type.



51
52
53
# File 'lib/dvdprofiler2xbmc/app_config.rb', line 51

def data_type
  @data_type
end

.helpObject (readonly)

Returns the value of attribute help.



51
52
53
# File 'lib/dvdprofiler2xbmc/app_config.rb', line 51

def help
  @help
end

.initialObject (readonly)

Returns the value of attribute initial.



51
52
53
# File 'lib/dvdprofiler2xbmc/app_config.rb', line 51

def initial
  @initial
end

Returns the value of attribute navigation.



51
52
53
# File 'lib/dvdprofiler2xbmc/app_config.rb', line 51

def navigation
  @navigation
end

.validateObject (readonly)

Returns the value of attribute validate.



51
52
53
# File 'lib/dvdprofiler2xbmc/app_config.rb', line 51

def validate
  @validate
end

.validate_itemObject (readonly)

Returns the value of attribute validate_item.



51
52
53
# File 'lib/dvdprofiler2xbmc/app_config.rb', line 51

def validate_item
  @validate_item
end

Class Method Details

.[](k) ⇒ Object

Synopsis

shortcut accessor for @config items



59
60
61
# File 'lib/dvdprofiler2xbmc/app_config.rb', line 59

def self.[](k)
  @config[k]
end

.[]=(k, v) ⇒ Object

Synopsis

shortcut accessor for @config items



65
66
67
# File 'lib/dvdprofiler2xbmc/app_config.rb', line 65

def self.[]=(k,v)
  @config[k] = v
end

.defaultObject

Synopsis

set the config to the default values



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
# File 'lib/dvdprofiler2xbmc/app_config.rb', line 159

def self.default
  # Note, all paths and extensions are case sensitive

  # this is the version of the rc file and is used to trigger
  # removal of no longer existing keys
  @config.version = '0.1.0'

  @config.color_enabled = true

  @navigation = [
      {'Application Options' => %w(color_enabled)},
      {'Setup Paths' => %w(directories subdirs_as_genres collection_filespec images_dir)},
      {'Setup Permissions'=> %w(file_permissions dir_permissions)},
      {'Setup Genre Mapping' => %w(genre_maps)},
      {'File Naming' => %w(media_extensions image_extensions naming)},
      {'Parsing' => %w(part_regex media_parsers)}
    ]

  @help.directories = [
      'Array of paths to scan for media.  Replace with your paths.'
    ].join("\n")
  @initial.directories = []
  # My directories are:
  @config.directories = [
#         '/media/dad-kubuntu/public/data/videos_iso',
#         '/media/dcerouter/public/data/videos_iso',
#         '/media/royw-gentoo/public/data/videos_iso',
#         '/media/royw-gentoo/public/data/movies'
    ]
  @data_type.directories = :ARRAY_OF_PATHSPECS
  @validate.directories = lambda do |directories|
    valid = false
    unless directories.empty?
      valid = true
      directories.each do |dir|
        unless File.exist?(dir) && File.directory?(dir)
          valid = false
        end
      end
    end
    valid
  end
  @validate_item.directories = lambda do |dir|
    dir.empty? || (File.exist?(dir) && File.directory?(dir))
  end

  @help.subdirs_as_genres = [
      'Directories underneath these will be added as genres to each .nfo file.',
      'For example:',
      '  /media/movies/Action/Bond/Goldeneye.m4v',
      'will add "Action" and "Bond" genres to Goldeneye.nfo',
      'Also note, that duplicate genres will be collapsed into single genres in the .nfo file.'
    ].join("\n")
  @initial.subdirs_as_genres = true
  @config.subdirs_as_genres = @initial.subdirs_as_genres
  @data_type.subdirs_as_genres = :BOOLEAN

  # Typical locations are:
  # @config.collection_filespec = File.join(ENV['HOME'], 'DVD Profiler/Databases/Exports/Collection.xml')
  # @config.images_dir = File.join(ENV['HOME'], 'DVD Profiler/Databases/Default/Images')
  #
  @help.collection_filespec = [
      'The location of DVD Profiler\'s exported Collection.xml'
    ].join("\n")
  @initial.collection_filespec = '~/DVD Profiler/Databases/Exports/Collection.xml'
  # My location is:
  @config.collection_filespec = @initial.collection_filespec
#     @config.collection_filespec = '/home/royw/DVD Profiler/Shared/Collection.xml'
  @data_type.collection_filespec = :FILESPEC
  @validate.collection_filespec = lambda do |filespec|
    File.exist?(filespec) && File.file?(filespec)
  end
  @validate_item.collection_filespec = lambda do |filespec|
    filespec.empty? || (File.exist?(filespec) && File.file?(filespec))
  end

  @help.images_dir = [
      'The location of DVD Profiler\'s cover scan images.'
    ].join("\n")
  @initial.images_dir = '~/DVD Profiler/Databases/Exports/Images'
  # My location is:
  @config.images_dir = @initial.images_dir
#     @config.images_dir = '/home/royw/DVD Profiler/Shared/Images'
  @data_type.images_dir = :PATHSPEC
  @validate.images_dir = lambda do |directory|
    File.exist?(directory) && File.directory?(directory)
  end
  @validate_item.images_dir = lambda do |directory|
    directory.empty? || (File.exist?(directory) && File.directory?(directory))
  end

  # You will probably need to edit the MEDIA_EXTENSIONS to specify
  # the containers used in your library
  @help.media_extensions = [
      'The supported file extensions for movie media.',
      'You probably will not need to edit this list.'
    ].join("\n")
  @initial.media_extensions = %w(iso m4v mp4 mpeg wmv asf flv mkv mov aac nut ogg ogm ram rm rv ra rmvb 3gp vivo pva nuv nsv nsa fli flc)
  @config.media_extensions = @initial.media_extensions
  @data_type.media_extensions = :ARRAY_OF_STRINGS
  @validate.media_extensions = lambda do |extensions|
    !extensions.collect{|ext| ext.blank? ? nil : ext}.compact.empty?
  end
  @validate_item.media_extensions = lambda do |extension|
    true
  end

  # You probably will not need to change these
  # Source file extensions.
  @help.image_extensions = [
      'The file extensions for image files such as cover art, fan art, and thumbnails.',
      'You probably will not need to edit this list.'
    ].join("\n")
  @initial.image_extensions = %w(jpg jpeg png gif bmp tbn)
  @config.image_extensions  = @initial.image_extensions
  @data_type.image_extensions = :ARRAY_OF_STRINGS
  @validate.image_extensions = lambda do |extensions|
    !extensions.collect{|ext| ext.blank? ? nil : ext}.compact.empty?
  end
  @validate_item.media_extensions = lambda do |extension|
    true
  end

  # map some genre names
  @help.genre_maps = [
      'Change the name of genres.',
      'For example, "SciFi" can be mapped to "Science Fiction"'
    ].join("\n")
  @initial.genre_maps = {
    'SciFi'           => 'Science Fiction',
    'Sci-Fi'          => 'Science Fiction',
    'Science-Fiction' => 'Science Fiction',
    'Anime'           => 'Animation',
    'Musical'         => 'Musicals',
    'Music'           => 'Musicals',
    'War Film'        => 'War',
    'Western'         => 'Westerns'
  }
  @config.genre_maps = @initial.genre_maps
  @data_type.genre_maps = :HASH_STRING_KEYS_STRING_VALUES

  @help.file_permissions = [
      'Set the file permissions of all files in the scanned directories to this value.',
      'This is useful to maintain consistancy of file permissions'
    ].join("\n")
  @initial.file_permissions = 0664.to_s(8)
  @config.file_permissions = @initial.file_permissions
  @data_type.file_permissions = :PERMISSIONS
  @validate.file_permissions = lambda do |permissions|
    (permissions.to_i(8) >= 0) && (permissions.to_i(8) <= 07777)
  end
  @validate_item.file_permissions = lambda do |permissions|
    permissions.empty? || ((permissions.to_i(8) >= 0) && (permissions.to_i(8) <= 07777))
  end

  @help.dir_permissions = [
      'Set the directory permissions of all sub-directories in the scanned directories to this value.',
      'This is useful to maintain consistancy of directory permissions'
    ].join("\n")
  @initial.dir_permissions = 0777.to_s(8)
  @config.dir_permissions = @initial.dir_permissions
  @data_type.dir_permissions = :PERMISSIONS
  @validate.dir_permissions = lambda do |permissions|
    permissions.empty? || ((permissions.to_i(8) >= 0) && (permissions.to_i(8) <= 07777))
  end

  # This maps the file type to extension.
  # The one unusual case in the list is for :fanart where
  # the actually media extension will be appended to this
  # extension (see FanartController)
  @help.extensions = [
      'Internally used to map types to file extensions.',
      'You may change the values if you need different file extensions.',
      'Do not change the keys unless you really know what you are doing!'
    ].join("\n")
  @initial.extensions  = {
      :fanart           => '-fanart',
      :thumbnail        => 'tbn',
      :nfo              => 'nfo',
      :dvdprofiler_xml  => 'dvdprofiler.xml',
      :imdb_xml         => 'imdb.xml',
      :tmdb_xml         => 'tmdb.xml',
      :new              => 'new',
      :backup           => '~',
      :isbn             => 'isbn',
      :imdb             => 'imdb',
      :no_isbn          => 'no_isbn',
      :no_imdb_lookup   => 'no_imdb_lookup',
      :no_tmdb_lookup   => 'no_tmdb_lookup',
    }
  @config.extensions  = @initial.extensions

  # substitutions:
  #  %t  => movie title
  #  %e  => extension from @config.extensions
  #  %p  => part
  @help.naming = [
      'Defines the various formatting of generated file names.',
      'Do not change the naming keys (ex: :fanart, :thumbnail,...).',
      'The :part key/value defines the format for a multi-part media while :no_part defines the format for single part media.',
      'The substutions are:',
      '  %t => movie title',
      '  %e => appropriate file extension',
      '  %p => the part substring from the media file (ex: \'cd1\', \'disc3\')',
      '  %r => video resolution',
      '  %y => year'
    ].join("\n")
  @initial.naming = {
      :fanart          => {:part => '%t%e',  :no_part => '%t%e'},
      :thumbnail       => {:part => '%t.%e', :no_part => '%t.%e'},
      :nfo             => {:part => '%t.%e', :no_part => '%t.%e'},
      :dvdprofiler_xml => {:part => '%t.%e', :no_part => '%t.%e'},
      :imdb_xml        => {:part => '%t.%e', :no_part => '%t.%e'},
      :tmdb_xml        => {:part => '%t.%e', :no_part => '%t.%e'}
    }
  @config.naming = @initial.naming

  # recognized multi-part tokens where N is an integer:
  #  *.cdN.*
  #  *.ptN.*
  #  *.diskN.*
  #  *.discN.*
  @help.part_regex = [
      'The regular expression for parsing the part sub-string from the media file.',
      'For example to find "cd2" in "movie.cd2.avi"'
    ].join("\n")
  @initial.part_regex = /\.(cd|pt|disk|disc)\d+/i
  @config.part_regex = @initial.part_regex

  # media filename parsers.
  # The :tokens array refers to the matches in the regex, ex:
  #  {:regex => /^\s*(.*\S)\s*\.([^.]+)\s*$/, :tokens => [:title, :extension]}
  # :title will be assigned the first match (.*\S) and
  # :extension will be assigned the second match ([^.]+)
  # See (Media.parse)
  @help.media_parsers = [
      'Media filename parsers.',
      'The :tokens array refers to the matches in the regex, ex:',
      '  {:regex => /^\s*(.*\S)\s*\.([^.]+)\s*$/, :tokens => [:title, :extension]}',
      ':title will be assigned the first match (.*\S) and',
      ':extension will be assigned the second match ([^.]+).',
      'Valid tokens are:  :title, :year, :resolution, :part, :extension'
    ].join("\n")
  @initial.media_parsers = [
    # "movie title - yyyy[res].partN.ext"
    {:regex => /^\s*(.*\S)\s*\-\s*(0|\d{4})\s*\[(\S*)\]\s*\.(cd\d+|pt\d+|disk\d+|disc\d+)\.([^.]+)\s*$/,
    :tokens => [:title, :year, :resolution, :part, :extension]
    },
    # "movie title (yyyy)[res].partN.ext"
    {:regex => /^\s*(.*\S)\s*\(\s*(0|\d{4})\s*\)\s*\[(\S*)\]\s*\.(cd\d+|pt\d+|disk\d+|disc\d+)\.([^.]+)\s*$/,
    :tokens => [:title, :year, :resolution, :part, :extension]
    },
    # "movie title[res].partN.ext"
    {:regex => /^\s*(.*\S)\s*\[(\S*)\]\s*\.(cd\d+|pt\d+|disk\d+|disc\d+)\.([^.]+)\s*$/,
    :tokens => [:title, :resolution, :part, :extension]
    },
    # "movie title - yyyy[res].ext"
    {:regex => /^\s*(.*\S)\s*\-\s*(0|\d{4})\s*\[(\S*)\]\s*\.([^.]+)\s*$/,
    :tokens => [:title, :year, :resolution, :extension]
    },
    # "movie title (yyyy)[res].ext"
    {:regex => /^\s*(.*\S)\s*\(\s*(0|\d{4})\s*\)\s*\[(\S*)\]\s*\.([^.]+)\s*$/,
    :tokens => [:title, :year, :resolution, :extension]
    },
    # "movie title[res].ext"
    {:regex => /^\s*(.*\S)\s*\[(\S*)\]\s*\.([^.]+)\s*$/,
    :tokens => [:title, :resolution, :extension]
    },
    # "movie title - yyyy.partN.ext"
    {:regex => /^\s*(.*\S)\s*\-\s*(0|\d{4})\s*\.(cd\d+|pt\d+|disk\d+|disc\d+)\.([^.]+)\s*$/,
    :tokens => [:title, :year, :part, :extension]
    },
    # "movie title (yyyy).partN.ext"
    {:regex => /^\s*(.*\S)\s*\(\s*(0|\d{4})\s*\)\s*\.(cd\d+|pt\d+|disk\d+|disc\d+)\.([^.]+)\s*$/,
    :tokens => [:title, :year, :part, :extension]
    },
    # "movie title.partN.ext"
    {:regex => /^\s*(.*\S)\s*\.(cd\d+|pt\d+|disk\d+|disc\d+)\.([^.]+)\s*$/,
    :tokens => [:title, :part, :extension]
    },
    # "movie title - yyyy.ext"
    {:regex => /^\s*(.*\S)\s*\-\s*(0|\d{4})\s*\.([^.]+)\s*$/,
    :tokens => [:title, :year, :extension]
    },
    # "movie title (yyyy).ext"
    {:regex => /^\s*(.*\S)\s*\(\s*(0|\d{4})\s*\)\s*\.([^.]+)\s*$/,
    :tokens => [:title, :year, :extension]
    },
    # "movie title.ext"
    {:regex => /^\s*(.*\S)\s*\.([^.]+)\s*$/,
    :tokens => [:title, :extension]
    }
  ]
  @config.media_parsers = @initial.media_parsers

  @help.do_update = [
      'Perform update.'
    ].join("\n")
  @initial.do_update = true
  @config.do_update = @initial.do_update
end

.exist?Boolean

Synopsis

does the config file exist?

Returns:

  • (Boolean)


71
72
73
# File 'lib/dvdprofiler2xbmc/app_config.rb', line 71

def self.exist?
  File.exist?(@yaml_filespec)
end

.loadObject

Synopsis

load the config file, overwriting current values



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/dvdprofiler2xbmc/app_config.rb', line 77

def self.load
  begin
    if File.exist?(@yaml_filespec)
      cfg = YAML.load_file(@yaml_filespec)
      cfg.delete('logger')
      if cfg.version != @config.version
        AppConfig[:logger].info {"config file (#{@yaml_filespec}) version mismatch"}
        AppConfig[:logger].info {"file version => #{cfg.version}"}
        AppConfig[:logger].info {"config version => #{@config.version}"}
        # remove from @config any keys that are not in cfg
        file_keys = cfg.keys.sort
        current_keys = @config.keys.sort
        intersection_keys = file_keys & current_keys
        obsolete_keys = file_keys - intersection_keys
        obsolete_keys.each do |key|
          AppConfig[:logger].info { "removing obsolete key #{key}"}
          cfg.delete(key)
        end
        cfg.delete('version')
      end
      @config.merge! cfg
    end
  rescue Exception => e
    AppConfig[:logger].error { "Error loading config file \"#{@yaml_filespec} - " + e.to_s + "\n" + e.backtrace.join("\n") }
  end
end

.saveObject

Synopsis

save the config file



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/dvdprofiler2xbmc/app_config.rb', line 106

def self.save
  begin
    unless @config.blank?
      File.delete(@yaml_filespec) if File.exist?(@yaml_filespec)
      AppConfig[:logger].info { "saving: #{@yaml_filespec}" }
      File.open(@yaml_filespec, "w") do |f|
        cfg = @config
        cfg.delete('logger')
        YAML.dump(cfg, f)
      end
    end
  rescue Exception => e
    AppConfig[:logger].error { "Error saving config file \"#{@yaml_filespec} - " + e.to_s + "\n" + e.backtrace.join("\n")}
  end
end

.to_sObject

Synopsis

generate a string for displaying the current config



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/dvdprofiler2xbmc/app_config.rb', line 124

def self.to_s
  buf = []
  @navigation.each do |page|
    page.each do |heading, keys|
      buf << heading
      buf << ''
      keys.each do |key|
        buf << key
        buf << @help[key].split("\n").collect{|line| "  " + line}.join("\n") unless @help[key].blank?
        buf << "Initial:"
        buf << @initial[key].pretty_inspect.collect{|line| "  " + line.rstrip}
        buf << "Current:"
        buf << @config[key].pretty_inspect.collect{|line| "  " + line.rstrip}
        buf << ''
      end
      buf << ''
    end
  end
  buf.join("\n")
end

.valid?Boolean

Synopsis

is the current config valid?

Returns:

  • (Boolean)


147
148
149
150
151
152
153
154
155
# File 'lib/dvdprofiler2xbmc/app_config.rb', line 147

def self.valid?
  valid = true
  @validate.each do |field, value|
    unless @validate[field].call(@config[field])
      valid = false
    end
  end
  valid
end