]> git.sesse.net Git - casparcg/blob - modules/psd/descriptor.cpp
Initial XML format for scenes and timeline support for PSD
[casparcg] / modules / psd / descriptor.cpp
1 /*
2 * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>
3 *
4 * This file is part of CasparCG (www.casparcg.com).
5 *
6 * CasparCG is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * CasparCG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with CasparCG. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * Author: Niklas P Andersson, niklas.p.andersson@svt.se
20 */
21
22 #include <memory>
23 #include "descriptor.h"
24 #include <boost\property_tree\ptree.hpp>
25 #include "misc.h"
26
27 namespace caspar { namespace psd {
28
29         class descriptor::context::scoped_holder
30         {
31                 descriptor::context::ptr_type ctx_;
32         public:
33                 explicit scoped_holder(const std::wstring& key, descriptor::context::ptr_type ctx) : ctx_(ctx) 
34                 {
35                         Ptree *parent = ctx_->stack.back();
36                         Ptree *child = &parent->push_back(std::make_pair(key, Ptree()))->second;
37                         ctx_->stack.push_back(child);
38                 }
39                 ~scoped_holder()
40                 {
41                         ctx_->stack.pop_back();
42                 }
43         };
44
45         descriptor::descriptor() : context_(std::make_shared<context>())
46         {
47                 context_->stack.push_back(&context_->root);
48         }
49         descriptor::descriptor(const std::wstring& key, context::ptr_type context) : context_(context)
50         {
51                 Ptree *parent = context_->stack.back();
52                 Ptree *child = &parent->push_back(std::make_pair(key, Ptree()))->second;
53                 context->stack.push_back(child);
54         }
55         descriptor::~descriptor()
56         {
57                 context_->stack.pop_back();
58         }
59
60 bool descriptor::populate(BEFileInputStream& stream)
61 {
62         bool result = true;
63
64         try
65         {
66                 stream.read_unicode_string();
67                 stream.read_id_string();
68                 unsigned long element_count = stream.read_long();
69                 for(int element_index = 0; element_index < element_count; ++element_index)
70                 {
71                         std::wstring key = stream.read_id_string();
72                         read_value(key, stream);
73                 }
74         }
75         catch(std::exception& ex)
76         {
77                 result = false;
78         }
79
80         return result;
81 }
82
83 void descriptor::read_value(const std::wstring& key, BEFileInputStream& stream)
84 {
85         unsigned int type = stream.read_long();
86
87         switch(type)
88         {
89         case 'Objc': 
90                 {
91                         descriptor desc(key, context_);
92                         desc.populate(stream);
93                 }
94                 break;
95
96         case 'doub': 
97                 {
98                         context_->stack.back()->put(key, stream.read_double());
99                 }
100                 break;
101
102         case 'TEXT':
103                 {
104                         context_->stack.back()->put(key, stream.read_unicode_string());
105                 }
106                 break;
107
108         case 'enum':
109                 {
110                         context_->stack.back()->put(stream.read_id_string(), stream.read_id_string());
111                 }
112                 break;
113
114         case 'long':
115                 {
116                         context_->stack.back()->put(key, static_cast<long>(stream.read_long()));
117                 }
118                 break;
119
120         case 'bool': 
121                 {
122                         context_->stack.back()->put(key, stream.read_byte());
123                 }
124                 break;
125
126         case 'VlLs': 
127                 {
128                         context::scoped_holder list(key, context_);
129                         unsigned long count = stream.read_long();
130                         for(int i = 0; i < count; ++i)
131                         {
132                                 read_value(L"li", stream);
133                         }
134                 }
135                 break;
136
137         case 'tdta':
138                 {
139                         unsigned long rawdata_length = stream.read_long();
140                         std::vector<char> rawdata(rawdata_length);
141                         stream.read(rawdata.data(), rawdata_length);
142
143                         std::wstring data_str(rawdata.begin(), rawdata.end());
144                         context_->stack.back()->put(key, data_str);
145                 }
146                 break;
147
148         case 'UntF': 
149                 {
150                         context::scoped_holder list(key, context_);
151                         unsigned long unit = stream.read_long();
152                         std::string type(reinterpret_cast<char*>(&unit), 4);
153                         std::wstring wtype(type.rbegin(), type.rend());
154                         context_->stack.back()->put(wtype, stream.read_double());
155                 }
156                 break;
157
158         case 'obj ': 
159         case 'GlbO': 
160         case 'type':
161         case 'GlbC':
162         case 'alis':
163         default:
164                 //descriptor type not supported yet
165                 throw PSDFileFormatException();
166         }
167 }
168
169 }       //namespace psd
170 }       //namespace caspar