/[svn]/gigedit/trunk/src/gigedit/global.h
ViewVC logotype

Annotation of /gigedit/trunk/src/gigedit/global.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3827 - (hide annotations) (download) (as text)
Tue Oct 6 16:58:03 2020 UTC (3 years, 6 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 11775 byte(s)
- global.h: Added util function unusedScripts().

1 schoenebeck 1396 /* -*- c++ -*-
2 schoenebeck 3712 * Copyright (C) 2007-2020 Andreas Persson
3 schoenebeck 1396 *
4     * This program is free software; you can redistribute it and/or
5     * modify it under the terms of the GNU General Public License as
6     * published by the Free Software Foundation; either version 2, or (at
7     * your option) any later version.
8     *
9     * This program is distributed in the hope that it will be useful, but
10     * WITHOUT ANY WARRANTY; without even the implied warranty of
11     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12     * General Public License for more details.
13     *
14     * You should have received a copy of the GNU General Public License
15     * along with program; see the file COPYING. If not, write to the Free
16     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
17     * 02110-1301 USA.
18     */
19    
20     #ifndef GIGEDIT_GLOBAL_H
21     #define GIGEDIT_GLOBAL_H
22    
23     #if HAVE_CONFIG_H
24     # include <config.h>
25     #endif
26    
27 schoenebeck 3151 #include <cstring>
28 schoenebeck 3341 #include <algorithm>
29 schoenebeck 3151
30 schoenebeck 3364 #ifdef GLIBMM_HEADER_FILE
31     # include GLIBMM_HEADER_FILE(glibmmconfig.h)
32     #else
33     # include <glibmmconfig.h>
34     #endif
35 schoenebeck 3151
36 schoenebeck 2967 #if !defined(WIN32)
37     # include <unistd.h>
38     # include <errno.h>
39     #endif
40    
41 persson 2442 #include <sstream>
42 schoenebeck 3089 #include <map>
43 schoenebeck 3547 #ifdef SIGCPP_HEADER_FILE
44     # include SIGCPP_HEADER_FILE(signal.h)
45     #else
46     # include <sigc++/signal.h>
47     #endif
48 persson 2442
49 schoenebeck 3089 #ifdef LIBGIG_HEADER_FILE
50     # include LIBGIG_HEADER_FILE(gig.h)
51 schoenebeck 3157 # include LIBGIG_HEADER_FILE(Serialization.h)
52 schoenebeck 3089 #else
53     # include <gig.h>
54 schoenebeck 3157 # include <Serialization.h>
55 schoenebeck 3089 #endif
56    
57 schoenebeck 2474 //FIXME: for some reason AC GETTEXT check fails on the Mac cross compiler?
58 schoenebeck 3364 #ifdef GETTEXT_HEADER_FILE
59     # include GETTEXT_HEADER_FILE(libintl.h)
60     #elif (HAVE_GETTEXT || defined(__APPLE__))
61 schoenebeck 1396 # include <libintl.h>
62     # define _(String) gettext(String)
63     #else
64     # define _(String) String
65     #endif
66    
67     #if defined(WIN32) && !HAVE_CONFIG_H
68     # include "../../win32/libgigedit_private.h" // like config.h, automatically generated by Dev-C++
69     # define PACKAGE "gigedit"
70     # define VERSION VER_STRING // VER_STRING defined in libgig_private.h
71     #endif // WIN32
72    
73 schoenebeck 2692 #define UNICODE_RIGHT_ARROW Glib::ustring(1, gunichar(0x2192))
74     #define UNICODE_LEFT_ARROW Glib::ustring(1, gunichar(0x2190))
75 schoenebeck 3155 #define UNICODE_SHIFT_KEY_SYMBOL Glib::ustring("\xe2\x87\xa7")
76     #if defined(__APPLE__)
77     # define UNICODE_ALT_KEY_SYMBOL Glib::ustring("\xe2\x8c\xa5")
78     #else
79     # define UNICODE_ALT_KEY_SYMBOL Glib::ustring("Alt")
80     #endif
81     #define UNICODE_ERASE_KEY_SYMBOL Glib::ustring("\xe2\x8c\xab")
82     #define UNICODE_CTRL_KEY_SYMBOL Glib::ustring("Ctrl")
83     #define UNICODE_CMD_KEY_SYMBOL Glib::ustring(1, gunichar(0x2318))
84     #if defined(__APPLE__)
85     # define UNICODE_PRIMARY_KEY_SYMBOL UNICODE_CMD_KEY_SYMBOL
86     #else
87     # define UNICODE_PRIMARY_KEY_SYMBOL UNICODE_CTRL_KEY_SYMBOL
88     #endif
89 schoenebeck 2692
90 schoenebeck 3123 // taken from gdk/gdkkeysyms.h
91     // (define on demand, to avoid unnecessary dev lib package build dependency)
92     #ifndef GDK_KEY_Control_L
93     # define GDK_KEY_Control_L 0xffe3
94     #endif
95     #ifndef GDK_KEY_Control_R
96     # define GDK_KEY_Control_R 0xffe4
97     #endif
98     #ifndef GDK_KEY_Left
99     # define GDK_KEY_Left 0xff51
100     #endif
101     #ifndef GDK_KEY_Right
102     # define GDK_KEY_Right 0xff53
103     #endif
104     #ifndef GDK_KEY_Up
105     # define GDK_KEY_Up 0xff52
106     #endif
107     #ifndef GDK_KEY_Down
108     # define GDK_KEY_Down 0xff54
109     #endif
110    
111 schoenebeck 3151 #include <glibmm/convert.h>
112    
113     #define GIG_STR_ENCODING "CP1252"
114    
115     static inline
116     Glib::ustring gig_to_utf8(const gig::String& gig_string) {
117     return Glib::convert_with_fallback(gig_string, "UTF-8", GIG_STR_ENCODING, "?");
118     }
119    
120     static inline
121     gig::String gig_from_utf8(const Glib::ustring& utf8_string) {
122     return Glib::convert_with_fallback(utf8_string, GIG_STR_ENCODING, "UTF-8", "?");
123     }
124    
125 schoenebeck 3340 inline Glib::ustring ltrim(Glib::ustring s) {
126     s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
127     return s;
128     }
129    
130     inline Glib::ustring rtrim(Glib::ustring s) {
131     s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
132     return s;
133     }
134    
135     inline Glib::ustring trim(Glib::ustring s) {
136     return ltrim(rtrim(s));
137     }
138    
139 persson 2442 template<class T> inline std::string ToString(T o) {
140     std::stringstream ss;
141     ss << o;
142     return ss.str();
143     }
144    
145 schoenebeck 3176 inline static bool endsWith(const std::string& haystack, const std::string& needle, bool caseSensitive) {
146     if (haystack.size() < needle.size()) return false;
147     const std::string sub = haystack.substr(haystack.size() - needle.size(), needle.size());
148     return (caseSensitive) ? (sub == needle) : (!strcasecmp(sub.c_str(), needle.c_str()));
149     }
150    
151 schoenebeck 3712 inline int getIndexOf(gig::Instrument* instrument) {
152     gig::File* file = (gig::File*) instrument->GetParent();
153     for (int i = 0; true ; ++i) {
154     gig::Instrument* instr = file->GetInstrument(i);
155     if (!instr) break;
156     if (instr == instrument) return i;
157     }
158     return -1;
159     }
160    
161 schoenebeck 3089 inline int getDimensionIndex(gig::dimension_t type, gig::Region* rgn) {
162     for (uint i = 0; i < rgn->Dimensions; ++i)
163     if (rgn->pDimensionDefinitions[i].dimension == type)
164     return i;
165     return -1;
166     }
167    
168     inline int getDimensionRegionIndex(gig::DimensionRegion* dr) {
169     if (!dr) return -1;
170     gig::Region* rgn = (gig::Region*)dr->GetParent();
171     for (uint i = 0; i < 256; ++i)
172     if (rgn->pDimensionRegions[i] == dr)
173     return i;
174     return -1;
175     }
176    
177 schoenebeck 2548 /// Find the number of bits required to hold the specified amount of zones.
178     inline int zoneCountToBits(int nZones) {
179 schoenebeck 2604 if (!nZones) return 0;
180 schoenebeck 2548 int iFinalBits = 0;
181     int zoneBits = nZones - 1;
182     for (; zoneBits > 1; iFinalBits += 2, zoneBits >>= 2);
183     iFinalBits += zoneBits;
184     return iFinalBits;
185     }
186    
187 schoenebeck 3089 /**
188     * Returns the sum of all bits of all dimensions defined before the given
189     * dimensions (@a type). This allows to access cases of that particular
190     * dimension directly. If the supplied dimension @a type does not exist in the
191     * the supplied @a region, then this function returns -1 instead!
192     *
193     * @param type - dimension that shall be used
194     * @param rgn - parent region of that dimension
195     */
196     inline int baseBits(gig::dimension_t type, gig::Region* rgn) {
197     int previousBits = 0;
198     for (uint i = 0; i < rgn->Dimensions; ++i) {
199     if (rgn->pDimensionDefinitions[i].dimension == type) return previousBits;
200     previousBits += rgn->pDimensionDefinitions[i].bits;
201     }
202     return -1;
203     }
204    
205     // key: dimension type, value: dimension's zone index
206     class DimensionCase : public std::map<gig::dimension_t,int> {
207     public:
208     bool isViolating(const DimensionCase& c) const {
209     for (DimensionCase::const_iterator it = begin(); it != end(); ++it) {
210     if (c.find(it->first) == c.end()) continue;
211     if (c.find(it->first)->second != it->second) return true;
212     }
213     return false;
214     }
215 schoenebeck 3123
216     // prevent passing gig::dimension_none from creating a new pair
217     // (TODO: other invalid gig::dimension_t values should be filtered here as well)
218     int& operator[](const gig::dimension_t& k) {
219     static int unused = 0;
220     if (k == gig::dimension_none) {
221     unused = 0;
222     return unused;
223     }
224     return std::map<gig::dimension_t,int>::operator[](k);
225     }
226 schoenebeck 3089 };
227    
228 schoenebeck 3123 //TODO: this function and caseOfDimRegion() from dimregionchooser.h are duplicates, eliminate either one of them!
229 schoenebeck 3089 inline DimensionCase dimensionCaseOf(gig::DimensionRegion* dr) {
230     DimensionCase dimCase;
231     int idr = getDimensionRegionIndex(dr);
232     if (idr < 0) return dimCase;
233     gig::Region* rgn = (gig::Region*)dr->GetParent();
234     int bitpos = 0;
235     for (int d = 0; d < rgn->Dimensions; ++d) {
236     const gig::dimension_def_t& dimdef = rgn->pDimensionDefinitions[d];
237     const int zone = (idr >> bitpos) & ((1 << dimdef.bits) - 1);
238     dimCase[dimdef.dimension] = zone;
239     bitpos += rgn->pDimensionDefinitions[d].bits;
240     }
241     return dimCase;
242     }
243    
244 schoenebeck 3307 /**
245     * Checks whether the passed dimension zones are within the boundaries of the
246     * defined dimensions. This is especially relevant if there are dimensions
247     * defined with an amount not equal to a power of two, in that case there are
248     * unused dimensions regions which should be ignored.
249     */
250     inline bool isUsedCase(const DimensionCase& c, gig::Region* rgn) {
251     for (int d = 0; d < rgn->Dimensions; ++d) {
252     gig::dimension_t type = rgn->pDimensionDefinitions[d].dimension;
253     if (c.find(type) == c.end()) continue;
254     int zone = c.find(type)->second;
255     if (zone < 0 || zone >= rgn->pDimensionDefinitions[d].zones)
256     return false;
257     }
258     return true;
259     }
260    
261     inline std::vector<gig::DimensionRegion*> dimensionRegionsMatching(
262     const DimensionCase& dimCase, gig::Region* rgn, bool skipUnusedZones = false)
263     {
264 schoenebeck 3089 std::vector<gig::DimensionRegion*> v;
265     for (int idr = 0; idr < 256; ++idr) {
266     if (!rgn->pDimensionRegions[idr]) continue;
267     DimensionCase c = dimensionCaseOf(rgn->pDimensionRegions[idr]);
268 schoenebeck 3307 if (dimCase.isViolating(c)) continue;
269     if (skipUnusedZones && !isUsedCase(c, rgn)) continue;
270     v.push_back(rgn->pDimensionRegions[idr]);
271 schoenebeck 3089 }
272     return v;
273     }
274    
275 schoenebeck 3123 inline gig::DimensionRegion* dimensionRegionMatching(const DimensionCase& dimCase, gig::Region* rgn) {
276     for (int idr = 0; idr < 256; ++idr) {
277     if (!rgn->pDimensionRegions[idr]) continue;
278     DimensionCase c = dimensionCaseOf(rgn->pDimensionRegions[idr]);
279     if (c == dimCase) return rgn->pDimensionRegions[idr];
280     }
281     return NULL;
282     }
283    
284 schoenebeck 3826 inline std::list<gig::Sample*> unusedSamples(gig::File* file) {
285     std::list<gig::Sample*> lsamples;
286     for (int iSample = 0; file->GetSample(iSample); ++iSample) {
287     gig::Sample* sample = file->GetSample(iSample);
288     bool isUsed = false;
289     for (gig::Instrument* instrument = file->GetFirstInstrument(); instrument;
290     instrument = file->GetNextInstrument())
291     {
292     for (gig::Region* rgn = instrument->GetFirstRegion(); rgn;
293     rgn = instrument->GetNextRegion())
294     {
295     for (int i = 0; i < 256; ++i) {
296     if (!rgn->pDimensionRegions[i]) continue;
297     if (rgn->pDimensionRegions[i]->pSample != sample) continue;
298     isUsed = true;
299     goto endOfRefSearch;
300     }
301     }
302     }
303     endOfRefSearch:
304     if (!isUsed) lsamples.push_back(sample);
305     }
306     return lsamples;
307     }
308    
309 schoenebeck 3827 inline std::vector<gig::Script*> unusedScripts(gig::File* file) {
310     std::vector<gig::Script*> scripts;
311     for (int iGroup = 0; file->GetScriptGroup(iGroup); ++iGroup) {
312     gig::ScriptGroup* group = file->GetScriptGroup(iGroup);
313     for (int iScript = 0; group->GetScript(iScript); ++iScript) {
314     gig::Script* script = group->GetScript(iScript);
315     bool isUsed = false;
316     for (gig::Instrument* instrument = file->GetFirstInstrument(); instrument;
317     instrument = file->GetNextInstrument())
318     {
319     for (int iSlot = 0; iSlot < instrument->ScriptSlotCount(); ++iSlot)
320     {
321     if (instrument->GetScriptOfSlot(iSlot) == script) {
322     isUsed = true;
323     goto endOfRefSearch;
324     }
325     }
326     }
327     endOfRefSearch:
328     if (!isUsed) scripts.push_back(script);
329     }
330     }
331     return scripts;
332     }
333    
334 schoenebeck 3177 template<typename T_Message>
335     class SignalGuard {
336     public:
337     SignalGuard(sigc::signal<void, T_Message>& start, sigc::signal<void, T_Message>& end, T_Message message)
338     : m_end(end), m_message(message)
339     {
340     if (message) start.emit(message);
341     }
342    
343     virtual ~SignalGuard() {
344     if (m_message) m_end.emit(m_message);
345     }
346     protected:
347     sigc::signal<void, T_Message>& m_end;
348     T_Message m_message;
349     };
350    
351 schoenebeck 1396 #endif // GIGEDIT_GLOBAL_H

  ViewVC Help
Powered by ViewVC