2008-06-02 17:41:35 -04:00
/*
2019-08-02 22:01:25 -04:00
* Copyright ( C ) 2007 - 2009 David Robillard < d @ drobilla . net >
* Copyright ( C ) 2007 - 2012 Tim Mayberry < mojofunk @ gmail . com >
* Copyright ( C ) 2008 - 2016 Paul Davis < paul @ linuxaudiosystems . com >
* Copyright ( C ) 2008 Hans Baier < hansfbaier @ googlemail . com >
* Copyright ( C ) 2009 - 2011 Carl Hetherington < carl @ carlh . net >
* Copyright ( C ) 2013 - 2019 Robin Gareus < robin @ gareus . org >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program 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
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License along
* with this program ; if not , write to the Free Software Foundation , Inc . ,
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
*/
2008-06-02 17:41:35 -04:00
2012-07-24 17:43:05 -04:00
# include <cerrno>
2012-06-23 01:06:54 -04:00
# include <glibmm/fileutils.h>
# include <glibmm/miscutils.h>
2009-02-25 13:26:51 -05:00
# include "pbd/error.h"
# include "pbd/compose.h"
2012-06-23 01:08:14 -04:00
# include "pbd/file_utils.h"
2015-12-18 11:46:08 -05:00
# include "pbd/openuri.h"
2008-06-02 17:41:35 -04:00
2009-02-25 13:26:51 -05:00
# include "ardour/directory_names.h"
# include "ardour/session_directory.h"
# include "ardour/utils.h"
2008-06-02 17:41:35 -04:00
2016-07-14 14:44:52 -04:00
# include "pbd/i18n.h"
2008-06-02 17:41:35 -04:00
namespace ARDOUR {
2009-05-12 13:03:42 -04:00
using namespace std ;
2008-06-02 17:41:35 -04:00
using namespace PBD : : sys ;
2015-11-19 10:08:04 -05:00
/* keep a static cache because SessionDirectory is used in various places. */
std : : map < std : : string , std : : string > SessionDirectory : : root_cache ;
2012-06-23 01:06:54 -04:00
SessionDirectory : : SessionDirectory ( const std : : string & session_path )
2008-06-02 17:41:35 -04:00
: m_root_path ( session_path )
{
}
2015-10-04 14:51:05 -04:00
SessionDirectory &
2011-07-14 13:41:06 -04:00
SessionDirectory : : operator = ( const std : : string & newpath )
{
m_root_path = newpath ;
2015-11-19 10:08:04 -05:00
root_cache . clear ( ) ;
2011-07-14 13:41:06 -04:00
return * this ;
}
2008-06-02 17:41:35 -04:00
bool
SessionDirectory : : create ( )
{
2012-06-23 01:06:54 -04:00
vector < std : : string > sub_dirs = sub_directories ( ) ;
for ( vector < std : : string > : : const_iterator i = sub_dirs . begin ( ) ; i ! = sub_dirs . end ( ) ; + + i )
2008-06-02 17:41:35 -04:00
{
2012-06-23 01:06:54 -04:00
if ( g_mkdir_with_parents ( i - > c_str ( ) , 0755 ) ! = 0 ) {
PBD : : error < < string_compose ( _ ( " Cannot create Session directory at path %1 Error: %2 " ) , * i , g_strerror ( errno ) ) < < endmsg ;
2012-06-23 03:33:31 -04:00
return false ;
2008-06-02 17:41:35 -04:00
}
}
2012-06-23 03:33:31 -04:00
return true ;
2008-06-02 17:41:35 -04:00
}
bool
SessionDirectory : : is_valid ( ) const
{
2012-06-23 01:06:54 -04:00
if ( ! Glib : : file_test ( m_root_path , Glib : : FILE_TEST_IS_DIR ) ) return false ;
2008-06-02 17:41:35 -04:00
2012-06-23 01:06:54 -04:00
vector < std : : string > sub_dirs = sub_directories ( ) ;
2008-06-02 17:41:35 -04:00
2012-06-23 01:06:54 -04:00
for ( vector < std : : string > : : iterator i = sub_dirs . begin ( ) ; i ! = sub_dirs . end ( ) ; + + i ) {
if ( ! Glib : : file_test ( * i , Glib : : FILE_TEST_IS_DIR ) ) {
PBD : : warning < < string_compose ( _ ( " Session subdirectory does not exist at path %1 " ) , * i ) < < endmsg ;
2008-06-02 17:41:35 -04:00
return false ;
}
}
return true ;
}
2012-06-23 01:06:54 -04:00
const std : : string
2008-06-02 17:41:35 -04:00
SessionDirectory : : old_sound_path ( ) const
{
2012-06-23 01:06:54 -04:00
return Glib : : build_filename ( m_root_path , old_sound_dir_name ) ;
2008-06-02 17:41:35 -04:00
}
2012-06-23 01:06:54 -04:00
const std : : string
2008-06-02 17:41:35 -04:00
SessionDirectory : : sources_root ( ) const
{
2015-11-19 10:08:04 -05:00
if ( root_cache . find ( m_root_path ) ! = root_cache . end ( ) ) {
return root_cache [ m_root_path ] ;
}
root_cache . clear ( ) ;
2012-06-23 01:08:51 -04:00
std : : string p = m_root_path ;
2015-11-19 10:08:04 -05:00
// TODO ideally we'd use the session's name() here, and not the containing folder's name.
2012-06-23 01:08:51 -04:00
std : : string filename = Glib : : path_get_basename ( p ) ;
2011-10-22 17:46:53 -04:00
2012-06-23 01:08:51 -04:00
if ( filename = = " . " ) {
2012-06-23 01:08:14 -04:00
p = PBD : : get_absolute_path ( m_root_path ) ;
2011-10-22 17:46:53 -04:00
}
2012-06-23 01:06:54 -04:00
2012-06-23 01:08:51 -04:00
const string legalized_root ( legalize_for_path ( Glib : : path_get_basename ( p ) ) ) ;
2008-06-02 17:41:35 -04:00
2012-06-23 01:08:51 -04:00
std : : string sources_root_path = Glib : : build_filename ( m_root_path , interchange_dir_name ) ;
2015-11-19 10:08:04 -05:00
/* check the interchange folder:
*
* 1 ) if a single subdir exists , use it , regardless of the name
* 2 ) if more than one dir is in interchange : abort , blame the user
* 3 ) if interchange does not exist or no subdir is present ,
* use the session - name to create one .
*
* We use the name of the containing folder , not the actual
* session name . The latter would require some API changes and
* careful libardour updates :
*
* The session object is created with the " snapshot-name " , only
* when loading the . ardour session file , the actual name is set .
*
* SessionDirectory is created with the session itself
* and picks up the wrong inital name .
*
* SessionDirectory is also used directly by the AudioRegionImporter ,
* and the peak - file background thread ( session . cc ) .
*
2019-04-13 13:19:29 -04:00
* There is no actual benefit to use the session - name instead of
* the folder - name . Under normal circumstances they are always
* identical . But it would be consistent to prefer the name .
2015-11-19 10:08:04 -05:00
*/
try {
Glib : : Dir dir ( sources_root_path ) ;
2015-12-05 10:35:41 -05:00
std : : list < std : : string > entries ;
2015-11-19 10:08:04 -05:00
2015-12-05 10:35:41 -05:00
for ( Glib : : DirIterator di = dir . begin ( ) ; di ! = dir . end ( ) ; di + + ) {
// ignore hidden files (eg. OS X ".DS_Store")
if ( ( * di ) . at ( 0 ) = = ' . ' ) {
continue ;
}
// and skip regular files (eg. Win Thumbs.db)
string fullpath = Glib : : build_filename ( sources_root_path , * di ) ;
if ( ! Glib : : file_test ( fullpath , Glib : : FILE_TEST_IS_DIR ) ) {
continue ;
}
entries . push_back ( * di ) ;
}
2015-12-05 10:07:45 -05:00
2015-11-19 10:08:04 -05:00
if ( entries . size ( ) = = 1 ) {
if ( entries . front ( ) ! = legalized_root ) {
PBD : : info < < _ ( " session-dir and session-name mismatch. Please use 'Menu > Session > Rename' in the future to rename sessions. " ) < < endmsg ;
}
root_cache [ m_root_path ] = Glib : : build_filename ( sources_root_path , entries . front ( ) ) ;
}
else if ( entries . size ( ) > 1 ) {
2016-02-17 10:29:25 -05:00
PBD : : open_folder ( sources_root_path ) ;
2015-11-19 11:04:02 -05:00
PBD : : fatal < < string_compose ( _ ( " The session's interchange dir is tainted. \n There is more than one folder in '%1'. \n Please remove extra subdirs to reduce possible filename ambiguties. " ) , sources_root_path ) < < endmsg ;
2015-11-19 10:08:04 -05:00
assert ( 0 ) ; // not reached
}
2018-10-26 07:40:03 -04:00
} catch ( Glib : : FileError const & ) {
2015-11-19 10:08:04 -05:00
;
}
if ( root_cache . find ( m_root_path ) = = root_cache . end ( ) ) {
root_cache [ m_root_path ] = Glib : : build_filename ( sources_root_path , legalized_root ) ;
}
return root_cache [ m_root_path ] ;
2008-06-02 17:41:35 -04:00
}
2012-10-23 10:52:26 -04:00
const std : : string
SessionDirectory : : sources_root_2X ( ) const
{
std : : string p = m_root_path ;
std : : string filename = Glib : : path_get_basename ( p ) ;
if ( filename = = " . " ) {
p = PBD : : get_absolute_path ( m_root_path ) ;
}
const string legalized_root ( legalize_for_path_2X ( Glib : : path_get_basename ( p ) ) ) ;
std : : string sources_root_path = Glib : : build_filename ( m_root_path , interchange_dir_name ) ;
return Glib : : build_filename ( sources_root_path , legalized_root ) ;
}
2012-06-23 01:06:54 -04:00
const std : : string
2008-06-02 17:41:35 -04:00
SessionDirectory : : sound_path ( ) const
{
2012-06-23 01:06:54 -04:00
if ( Glib : : file_test ( old_sound_path ( ) , Glib : : FILE_TEST_IS_DIR ) ) return old_sound_path ( ) ;
2008-06-02 17:41:35 -04:00
// the new style sound directory
2012-06-23 01:06:54 -04:00
return Glib : : build_filename ( sources_root ( ) , sound_dir_name ) ;
2008-06-02 17:41:35 -04:00
}
2012-10-23 10:52:26 -04:00
const std : : string
SessionDirectory : : sound_path_2X ( ) const
{
return Glib : : build_filename ( sources_root_2X ( ) , sound_dir_name ) ;
}
2012-06-23 01:06:54 -04:00
const std : : string
2008-06-02 17:41:35 -04:00
SessionDirectory : : midi_path ( ) const
{
2012-06-23 01:06:54 -04:00
return Glib : : build_filename ( sources_root ( ) , midi_dir_name ) ;
2008-06-02 17:41:35 -04:00
}
2008-12-08 04:50:19 -05:00
2013-03-12 17:00:09 -04:00
const std : : string
SessionDirectory : : video_path ( ) const
{
return Glib : : build_filename ( sources_root ( ) , video_dir_name ) ;
}
2012-06-23 01:06:54 -04:00
const std : : string
2008-06-02 17:41:35 -04:00
SessionDirectory : : peak_path ( ) const
{
2012-06-23 01:06:54 -04:00
return Glib : : build_filename ( m_root_path , peak_dir_name ) ;
2008-06-02 17:41:35 -04:00
}
2012-06-23 01:06:54 -04:00
const std : : string
2011-03-01 16:54:54 -05:00
SessionDirectory : : dead_path ( ) const
2008-06-02 17:41:35 -04:00
{
2012-06-23 01:06:54 -04:00
return Glib : : build_filename ( m_root_path , dead_dir_name ) ;
2008-06-02 17:41:35 -04:00
}
2012-06-23 01:06:54 -04:00
const std : : string
2008-06-02 17:41:35 -04:00
SessionDirectory : : export_path ( ) const
{
2012-06-23 01:06:54 -04:00
return Glib : : build_filename ( m_root_path , export_dir_name ) ;
2008-06-02 17:41:35 -04:00
}
2018-07-14 13:46:49 -04:00
const std : : string
SessionDirectory : : backup_path ( ) const
{
return Glib : : build_filename ( m_root_path , backup_dir_name ) ;
}
2012-06-23 01:06:54 -04:00
const vector < std : : string >
2008-06-02 17:41:35 -04:00
SessionDirectory : : sub_directories ( ) const
{
2012-06-23 01:06:54 -04:00
vector < std : : string > tmp_paths ;
2008-06-02 17:41:35 -04:00
2011-03-01 16:54:54 -05:00
tmp_paths . push_back ( sound_path ( ) ) ;
tmp_paths . push_back ( midi_path ( ) ) ;
2015-01-14 17:53:23 -05:00
tmp_paths . push_back ( video_path ( ) ) ;
2011-03-01 16:54:54 -05:00
tmp_paths . push_back ( peak_path ( ) ) ;
tmp_paths . push_back ( dead_path ( ) ) ;
tmp_paths . push_back ( export_path ( ) ) ;
2018-07-14 13:46:49 -04:00
tmp_paths . push_back ( backup_path ( ) ) ;
2008-06-02 17:41:35 -04:00
return tmp_paths ;
}
} // namespace ARDOUR