Panda3D
androidLogStream.cxx
1 // Filename: androidLogStream.cxx
2 // Created by: rdb (12Jan13)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "androidLogStream.h"
16 #include "configVariableString.h"
17 
18 #ifdef ANDROID
19 
20 #include <android/log.h>
21 
22 ////////////////////////////////////////////////////////////////////
23 // Function: AndroidLogStreamBuf::Constructor
24 // Access: Public
25 // Description:
26 ////////////////////////////////////////////////////////////////////
27 AndroidLogStream::AndroidLogStreamBuf::
28 AndroidLogStreamBuf(int priority) :
29  _priority(priority) {
30 
31  static ConfigVariableString android_log_tag
32  ("android-log-tag", "Panda3D",
33  PRC_DESC("This defines the tag that Panda3D will use when writing to the "
34  "Android log. The default is \"Panda3D\"."));
35 
36  if (_tag.empty()) {
37  _tag = android_log_tag.get_value();
38  }
39 
40  // The AndroidLogStreamBuf doesn't actually need a buffer--it's happy
41  // writing characters one at a time, since they're just getting
42  // stuffed into a string. (Although the code is written portably
43  // enough to use a buffer correctly, if we had one.)
44  setg(0, 0, 0);
45  setp(0, 0);
46 }
47 
48 ////////////////////////////////////////////////////////////////////
49 // Function: AndroidLogStreamBuf::Destructor
50 // Access: Public, Virtual
51 // Description:
52 ////////////////////////////////////////////////////////////////////
53 AndroidLogStream::AndroidLogStreamBuf::
54 ~AndroidLogStreamBuf() {
55  sync();
56 }
57 
58 ////////////////////////////////////////////////////////////////////
59 // Function: AndroidLogStreamBuf::sync
60 // Access: Public, Virtual
61 // Description: Called by the system ostream implementation when the
62 // buffer should be flushed to output (for instance, on
63 // destruction).
64 ////////////////////////////////////////////////////////////////////
65 int AndroidLogStream::AndroidLogStreamBuf::
66 sync() {
67  streamsize n = pptr() - pbase();
68 
69  // Write the characters that remain in the buffer.
70  for (char *p = pbase(); p < pptr(); ++p) {
71  write_char(*p);
72  }
73 
74  pbump(-n); // Reset pptr().
75  return 0; // EOF to indicate write full.
76 }
77 
78 ////////////////////////////////////////////////////////////////////
79 // Function: AndroidLogStreamBuf::overflow
80 // Access: Public, Virtual
81 // Description: Called by the system ostream implementation when its
82 // internal buffer is filled, plus one character.
83 ////////////////////////////////////////////////////////////////////
84 int AndroidLogStream::AndroidLogStreamBuf::
85 overflow(int ch) {
86  streamsize n = pptr() - pbase();
87 
88  if (n != 0 && sync() != 0) {
89  return EOF;
90  }
91 
92  if (ch != EOF) {
93  // Write one more character.
94  write_char(ch);
95  }
96 
97  return 0;
98 }
99 
100 ////////////////////////////////////////////////////////////////////
101 // Function: AndroidLogStreamBuf::write_char
102 // Access: Private
103 // Description: Stores a single character.
104 ////////////////////////////////////////////////////////////////////
105 void AndroidLogStream::AndroidLogStreamBuf::
106 write_char(char c) {
107  if (c == '\n') {
108  // Write a line to the log file.
109  __android_log_write(_priority, _tag.c_str(), _data.c_str());
110  _data.clear();
111  } else {
112  _data += c;
113  }
114 }
115 
116 ////////////////////////////////////////////////////////////////////
117 // Function: AndroidLogStream::Constructor
118 // Access: Private
119 // Description:
120 ////////////////////////////////////////////////////////////////////
121 AndroidLogStream::
122 AndroidLogStream(int priority) :
123  ostream(new AndroidLogStreamBuf(priority)) {
124 }
125 
126 ////////////////////////////////////////////////////////////////////
127 // Function: AndroidLogStream::Destructor
128 // Access: Public, Virtual
129 // Description:
130 ////////////////////////////////////////////////////////////////////
131 AndroidLogStream::
132 ~AndroidLogStream() {
133  delete rdbuf();
134 }
135 
136 ////////////////////////////////////////////////////////////////////
137 // Function: AndroidLogStream::out
138 // Access: Public, Static
139 // Description: Returns an AndroidLogStream suitable for writing
140 // log messages with the indicated severity.
141 ////////////////////////////////////////////////////////////////////
142 ostream &AndroidLogStream::
143 out(NotifySeverity severity) {
144  static AndroidLogStream* streams[NS_fatal + 1] = {NULL};
145 
146  if (streams[severity] == NULL) {
147  int priority = ANDROID_LOG_UNKNOWN;
148  if (severity != NS_unspecified) {
149  priority = ((int)severity) + 1;
150  }
151  streams[severity] = new AndroidLogStream(priority);
152  }
153 
154  return *streams[severity];
155 }
156 
157 #endif // ANDROID
This is a convenience class to specialize ConfigVariable as a string type.