KiCad PCB EDA Suite
io_mgr.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2011-2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
5  * Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include <wx/filename.h>
26 #include <wx/uri.h>
27 
31 #include <config.h>
32 #include <eagle_plugin.h>
33 #include <gpcb_plugin.h>
34 #include <io_mgr.h>
35 #include <kicad_plugin.h>
36 #include <legacy_plugin.h>
38 
39 #if defined(BUILD_GITHUB_PLUGIN)
40  #include <github/github_plugin.h>
41 #endif
42 
44 
45 #define FMT_UNIMPLEMENTED _( "Plugin \"%s\" does not implement the \"%s\" function." )
46 #define FMT_NOTFOUND _( "Plugin type \"%s\" is not found." )
47 
48 
49 // Some day plugins might be in separate DLL/DSOs, simply because of numbers of them
50 // and code size. Until then, use the simplest method:
51 
52 // This implementation is one of two which could be done.
53 // The other one would cater to DLL/DSO's. But since it would be nearly
54 // impossible to link a KICAD type DLL/DSO right now without pulling in all
55 // ::Draw() functions, I forgo that option temporarily.
56 
57 // Some day it may be possible to have some built in AND some DLL/DSO
58 // plugins coexisting.
59 
60 
62 {
63  // This implementation is subject to change, any magic is allowed here.
64  // The public IO_MGR API is the only pertinent public information.
65 
66  return PLUGIN_REGISTRY::Instance()->Create( aFileType );
67 }
68 
69 
70 void IO_MGR::PluginRelease( PLUGIN* aPlugin )
71 {
72  // This function is a place holder for a future point in time where
73  // the plugin is a DLL/DSO. It could do reference counting, and then
74  // unload the DLL/DSO when count goes to zero.
75 
76  delete aPlugin;
77 }
78 
79 
80 const wxString IO_MGR::ShowType( PCB_FILE_T aType )
81 {
82  const auto& plugins = PLUGIN_REGISTRY::Instance()->AllPlugins();
83 
84  for( const auto& plugin : plugins )
85  {
86  if ( plugin.m_type == aType )
87  {
88  return plugin.m_name;
89  }
90  }
91 
92  return wxString::Format( _( "UNKNOWN (%d)" ), aType );
93 }
94 
95 
96 IO_MGR::PCB_FILE_T IO_MGR::EnumFromStr( const wxString& aType )
97 {
98  const auto& plugins = PLUGIN_REGISTRY::Instance()->AllPlugins();
99 
100  for( const auto& plugin : plugins )
101  {
102  if ( plugin.m_name == aType )
103  {
104  return plugin.m_type;
105  }
106  }
107 
108  return PCB_FILE_T( -1 );
109 }
110 
111 
112 const wxString IO_MGR::GetFileExtension( PCB_FILE_T aFileType )
113 {
114  wxString ext = wxEmptyString;
115  PLUGIN* plugin = PluginFind( aFileType );
116 
117  if( plugin != NULL )
118  {
119  ext = plugin->GetFileExtension();
120  PluginRelease( plugin );
121  }
122 
123  return ext;
124 }
125 
126 
128 {
129  PCB_FILE_T ret = KICAD_SEXP; // default guess, unless detected otherwise.
130  wxFileName fn( aLibPath );
131 
132  if( fn.GetExt() == LegacyFootprintLibPathExtension )
133  {
134  ret = LEGACY;
135  }
136  else if( fn.GetExt() == GedaPcbFootprintLibFileExtension )
137  {
138  ret = GEDA_PCB;
139  }
140  else if( fn.GetExt() == EagleFootprintLibPathExtension )
141  {
142  ret = EAGLE;
143  }
144 
145  // Test this one anyways, even though it's the default guess, to avoid
146  // the wxURI instantiation below.
147  // We default ret to KICAD above, because somebody might have
148  // mistakenly put a pretty library into a directory other than
149  // *.pretty/ with *.kicad_mod in there., and I don't want to return -1,
150  // since we only claimed to be guessing.
151  //
152  // However libraries on GitHub have names ending by .pretty
153  // so test also this is not a name starting by http (including https).
154  else if( fn.GetExt() == KiCadFootprintLibPathExtension &&
155  !aLibPath.StartsWith( wxT( "http" ) ) )
156  {
157  ret = KICAD_SEXP;
158  }
159  else
160  {
161 #if defined(BUILD_GITHUB_PLUGIN)
162  // There is no extension for a remote repo, so test the server name.
163  wxURI uri( aLibPath );
164 
165  if( uri.HasServer() && uri.GetServer() == wxT( "github.com" ) )
166  {
167  ret = GITHUB;
168  }
169 #endif
170  }
171 
172  return ret;
173 }
174 
175 
176 BOARD* IO_MGR::Load( PCB_FILE_T aFileType, const wxString& aFileName,
177  BOARD* aAppendToMe, const PROPERTIES* aProperties )
178 {
179  // release the PLUGIN even if an exception is thrown.
180  PLUGIN::RELEASER pi( PluginFind( aFileType ) );
181 
182  if( (PLUGIN*) pi ) // test pi->plugin
183  {
184  return pi->Load( aFileName, aAppendToMe, aProperties ); // virtual
185  }
186 
187  THROW_IO_ERROR( wxString::Format( FMT_NOTFOUND, ShowType( aFileType ).GetData() ) );
188 }
189 
190 
191 void IO_MGR::Save( PCB_FILE_T aFileType, const wxString& aFileName, BOARD* aBoard, const PROPERTIES* aProperties )
192 {
193  // release the PLUGIN even if an exception is thrown.
194  PLUGIN::RELEASER pi( PluginFind( aFileType ) );
195 
196  if( (PLUGIN*) pi ) // test pi->plugin
197  {
198  pi->Save( aFileName, aBoard, aProperties ); // virtual
199  return;
200  }
201 
202  THROW_IO_ERROR( wxString::Format( FMT_NOTFOUND, ShowType( aFileType ).GetData() ) );
203 }
204 
205 // These text strings are "truth" for identifying the plugins. If you change the spellings,
206 // you will obsolete library tables, so don't do it. Additions are OK.
207 static IO_MGR::REGISTER_PLUGIN registerEaglePlugin( IO_MGR::EAGLE, wxT("Eagle"), []() -> PLUGIN* { return new EAGLE_PLUGIN; } );
208 static IO_MGR::REGISTER_PLUGIN registerKicadPlugin( IO_MGR::KICAD_SEXP, wxT("KiCad"), []() -> PLUGIN* { return new PCB_IO; } );
209 static IO_MGR::REGISTER_PLUGIN registerPcadPlugin( IO_MGR::PCAD, wxT("P-Cad"), []() -> PLUGIN* { return new PCAD_PLUGIN; } );
211  wxT( "Altium Designer" ), []() -> PLUGIN* { return new ALTIUM_DESIGNER_PLUGIN; } );
213  wxT( "Altium Circuit Studio" ),
214  []() -> PLUGIN* { return new ALTIUM_CIRCUIT_STUDIO_PLUGIN; } );
216  wxT( "Altium Circuit Maker" ),
217  []() -> PLUGIN* { return new ALTIUM_CIRCUIT_MAKER_PLUGIN; } );
218 #ifdef BUILD_GITHUB_PLUGIN
219 static IO_MGR::REGISTER_PLUGIN registerGithubPlugin( IO_MGR::GITHUB, wxT("Github"), []() -> PLUGIN* { return new GITHUB_PLUGIN; } );
220 #endif /* BUILD_GITHUB_PLUGIN */
221 static IO_MGR::REGISTER_PLUGIN registerLegacyPlugin( IO_MGR::LEGACY, wxT("Legacy"), []() -> PLUGIN* { return new LEGACY_PLUGIN; } );
222 static IO_MGR::REGISTER_PLUGIN registerGPCBPlugin( IO_MGR::GEDA_PCB, wxT("GEDA/Pcb"), []() -> PLUGIN* { return new GPCB_PLUGIN; } );
const std::string LegacyFootprintLibPathExtension
PLUGIN * Create(PCB_FILE_T aFileType) const
Definition: io_mgr.h:111
PCB_IO is a PLUGIN derivation for saving and loading Pcbnew s-expression formatted files.
virtual void Save(const wxString &aFileName, BOARD *aBoard, const PROPERTIES *aProperties=NULL)
Function Save will write aBoard to a storage file in a format that this PLUGIN implementation knows a...
Definition: plugin.cpp:53
GPCB_PLUGIN is a PLUGIN derivation for saving and loading Geda PCB files.
Definition: gpcb_plugin.h:47
static IO_MGR::REGISTER_PLUGIN registerLegacyPlugin(IO_MGR::LEGACY, wxT("Legacy"), []() -> PLUGIN *{ return new LEGACY_PLUGIN;})
static IO_MGR::REGISTER_PLUGIN registerAltiumCircuitMakerPlugin(IO_MGR::ALTIUM_CIRCUIT_MAKER, wxT("Altium Circuit Maker"), []() -> PLUGIN *{ return new ALTIUM_CIRCUIT_MAKER_PLUGIN;})
const std::string EagleFootprintLibPathExtension
static IO_MGR::REGISTER_PLUGIN registerAltiumCircuitStudioPlugin(IO_MGR::ALTIUM_CIRCUIT_STUDIO, wxT("Altium Circuit Studio"), []() -> PLUGIN *{ return new ALTIUM_CIRCUIT_STUDIO_PLUGIN;})
static const wxString ShowType(PCB_FILE_T aFileType)
Function ShowType returns a brief name for a plugin, given aFileType enum.
Definition: io_mgr.cpp:80
PROPERTIES is a name/value tuple with unique names and optional values.
Definition: properties.h:34
Geda PCB file formats.
Definition: io_mgr.h:63
static PCB_FILE_T GuessPluginTypeFromLibPath(const wxString &aLibPath)
Function GuessPluginTypeFromLibPath returns a plugin type given a footprint library's libPath.
Definition: io_mgr.cpp:127
static IO_MGR::REGISTER_PLUGIN registerGPCBPlugin(IO_MGR::GEDA_PCB, wxT("GEDA/Pcb"), []() -> PLUGIN *{ return new GPCB_PLUGIN;})
RELEASER releases a PLUGIN in the context of a potential thrown exception, through its destructor.
Definition: io_mgr.h:579
static IO_MGR::REGISTER_PLUGIN registerPcadPlugin(IO_MGR::PCAD, wxT("P-Cad"), []() -> PLUGIN *{ return new PCAD_PLUGIN;})
static IO_MGR::REGISTER_PLUGIN registerKicadPlugin(IO_MGR::KICAD_SEXP, wxT("KiCad"), []() -> PLUGIN *{ return new PCB_IO;})
EAGLE_PLUGIN works with Eagle 6.x XML board files and footprints to implement the Pcbnew PLUGIN API,...
Definition: eagle_plugin.h:118
#define NULL
LEGACY_PLUGIN is a PLUGIN derivation which could possibly be put into a DLL/DSO.
Definition: legacy_plugin.h:65
static PCB_FILE_T EnumFromStr(const wxString &aFileType)
Function EnumFromStr returns the PCB_FILE_T from the corresponding plugin type name: "kicad",...
Definition: io_mgr.cpp:96
static BOARD * Load(PCB_FILE_T aFileType, const wxString &aFileName, BOARD *aAppendToMe=NULL, const PROPERTIES *aProperties=NULL)
Function Load finds the requested PLUGIN and if found, calls the PLUGIN->Load(..) funtion on it using...
Definition: io_mgr.cpp:176
Definition of file extensions used in Kicad.
Class GITHUB_PLUGIN implements a portion of pcbnew's PLUGIN interface to provide read only access to ...
static IO_MGR::REGISTER_PLUGIN registerAltiumDesignerPlugin(IO_MGR::ALTIUM_DESIGNER, wxT("Altium Designer"), []() -> PLUGIN *{ return new ALTIUM_DESIGNER_PLUGIN;})
#define THROW_IO_ERROR(msg)
#define FMT_NOTFOUND
Definition: io_mgr.cpp:46
virtual const wxString GetFileExtension() const =0
Function GetFileExtension returns the file extension for the PLUGIN.
static void Save(PCB_FILE_T aFileType, const wxString &aFileName, BOARD *aBoard, const PROPERTIES *aProperties=NULL)
Function Save will write either a full aBoard to a storage file in a format that this implementation ...
Definition: io_mgr.cpp:191
static void PluginRelease(PLUGIN *aPlugin)
Function PluginRelease releases a PLUGIN back to the system, and may cause it to be unloaded from mem...
Definition: io_mgr.cpp:70
static IO_MGR::REGISTER_PLUGIN registerEaglePlugin(IO_MGR::EAGLE, wxT("Eagle"), []() -> PLUGIN *{ return new EAGLE_PLUGIN;})
static PLUGIN_REGISTRY * Instance()
Definition: io_mgr.h:91
Legacy Pcbnew file formats prior to s-expression.
Definition: io_mgr.h:56
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:180
Pcbnew PLUGIN for Altium *.PcbDoc format.
#define _(s)
Definition: 3d_actions.cpp:33
static PLUGIN * PluginFind(PCB_FILE_T aFileType)
Function PluginFind returns a PLUGIN which the caller can use to import, export, save,...
Definition: io_mgr.cpp:61
PLUGIN is a base class that BOARD loading and saving plugins should derive from.
Definition: io_mgr.h:273
const std::string GedaPcbFootprintLibFileExtension
const std::vector< ENTRY > & AllPlugins() const
Definition: io_mgr.h:123
PCB_FILE_T
Enum PCB_FILE_T is a set of file types that the IO_MGR knows about, and for which there has been a pl...
Definition: io_mgr.h:54
const std::string KiCadFootprintLibPathExtension
REGISTER_PLUGIN Registers a plugin.
Definition: io_mgr.h:139
virtual BOARD * Load(const wxString &aFileName, BOARD *aAppendToMe, const PROPERTIES *aProperties=NULL)
Function Load loads information from some input file format that this PLUGIN implementation knows abo...
Definition: plugin.cpp:46
S-expression Pcbnew file format.
Definition: io_mgr.h:57
static const wxString GetFileExtension(PCB_FILE_T aFileType)
Function GetFileExtension returns the file extension for aFileType.
Definition: io_mgr.cpp:112